From fae46e0edc31761e57026bda1a1337898fd1c36f Mon Sep 17 00:00:00 2001 From: Constantin Zackl Date: Fri, 14 Feb 2025 11:30:12 +0100 Subject: [PATCH 1/3] aded VisiumHD support --- R/visualization.R | 85 +++++++++++++++++++++------------- vignettes/spacedeconv_data.Rmd | 15 ++++++ 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/R/visualization.R b/R/visualization.R index d71aa093..9fc4ee4a 100644 --- a/R/visualization.R +++ b/R/visualization.R @@ -648,7 +648,8 @@ make_baseplot <- function(spe, df, to_plot, palette = "Mako", transform_scale = limits = NULL, smooth = FALSE, smoothing_factor = 1.5, title_size = 30, title = NULL, font_size = 15, legend_size = 20, density = TRUE, save = FALSE, path = NULL, png_width = 1500, png_height = 750, show_legend = TRUE, - nDigits = NULL, pseudocount = 1, shift_positive = TRUE) { + nDigits = NULL, pseudocount = 1, shift_positive = TRUE, + spot_shape = "hexagon") { if (is.null(spe)) { stop("Parameter 'spe' is null or missing, but is required") } @@ -751,14 +752,17 @@ make_baseplot <- function(spe, df, to_plot, palette = "Mako", transform_scale = legend_title <- title } - # preparing the dataframe with sf, inserting points - sf_points <- sf::st_as_sf(df, coords = c("pxl_col_in_fullres", "pxl_row_in_fullres")) + # Branch based on the spot_shape parameter: + if (spot_shape == "hexagon") { + # Prepare an sf object with spot centers + sf_points <- sf::st_as_sf(df, coords = c("pxl_col_in_fullres", "pxl_row_in_fullres")) - # generate hexagons - new_geom <- get_polygon_geometry(df, spot_distance, offset_rotation = offset_rotation) + # Generate hexagon polygons using the existing function + new_geom <- get_polygon_geometry(df, spot_distance, offset_rotation = offset_rotation) - # now overwrite the points with hex polygons - sf_poly <- sf::st_set_geometry(sf_points, new_geom) + # Overwrite the points with hexagon geometries + sf_poly <- sf::st_set_geometry(sf_points, new_geom) + } # Determine the palette type based on the palette name if (is.null(palette_type)) { @@ -788,19 +792,32 @@ make_baseplot <- function(spe, df, to_plot, palette = "Mako", transform_scale = # p <- p + annotation_raster(img, xmin = min(df$pxl_col_in_fullres), xmax = max(df$pxl_col_in_fullres), ymin = max(df$pxl_row_in_fullres), ymax = min(df$pxl_row_in_fullres)) } - # add hexagons - p <- p + - geom_sf(aes_string(fill = to_plot), lwd = 0, color = NA, data = sf_poly) + - # coord_sf(xlim = c(0, width), ylim = c(0, -height)) + - theme( - axis.text = element_blank(), - axis.ticks = element_blank(), - panel.grid = element_blank(), - panel.background = element_blank(), - plot.title = element_text(size = title_size, hjust = 0.5), - legend.text = element_text(size = font_size), - legend.key.size = unit(legend_size, "points") - ) + + # add SPOTS + if (spot_shape == "hexagon") { + p <- p + geom_sf(aes_string(fill = to_plot), lwd = 0, color = NA, data = sf_poly) + } else if (spot_shape == "square") { + p <- p + geom_tile(aes_string(x = "pxl_col_in_fullres", y = "pxl_row_in_fullres", fill = to_plot), + data = df, width = spot_distance, height = spot_distance) + } else if (spot_shape == "circle") { + # For circles, we use geom_point with shape 21. + # Here we approximate the circle size using spot_distance. The conversion factor may be adjusted. + circle_size <- spot_distance / 5 # Adjust this constant as needed. + p <- p + geom_point(aes_string(x = "pxl_col_in_fullres", y = "pxl_row_in_fullres", fill = to_plot), + data = df, shape = 21, size = circle_size, stroke = 0) + } else { + stop("Invalid spot_shape. Allowed values are 'hexagon', 'square', or 'circle'.") + } + + + p <- p + theme( + axis.text = element_blank(), + axis.ticks = element_blank(), + panel.grid = element_blank(), + panel.background = element_blank(), + plot.title = element_text(size = title_size, hjust = 0.5), + legend.text = element_text(size = font_size), + legend.key.size = unit(legend_size, "points") + ) + ggplot2::labs(title = legend_title, fill = element_blank()) # zoom if requested @@ -883,13 +900,20 @@ make_baseplot <- function(spe, df, to_plot, palette = "Mako", transform_scale = } # create density plot if requested - suppressMessages( + suppressMessages({ if (density && palette_type != "discrete") { - data <- data.frame(values = sf_poly[[to_plot]], id = rep(to_plot, nrow(sf_poly))) - density <- ggplot2::ggplot(data, mapping = ggplot2::aes_string(x = "values", y = "id")) + # fill... see ggridges docs - # ggplot2::geom_density() + - ggridges::geom_density_ridges() + # _gradient() - # ggplot2::scale_fill_viridis_c() + + # Determine which vector of values to use: + # For hexagons, use the values from sf_poly; for square/circle, use df. + values_data <- if (spot_shape == "hexagon" && exists("sf_poly")) { + sf_poly[[to_plot]] + } else { + df[[to_plot]] + } + + data <- data.frame(values = values_data, id = rep(to_plot, length(values_data))) + + density_plot <- ggplot2::ggplot(data, mapping = ggplot2::aes_string(x = "values", y = "id")) + + ggridges::geom_density_ridges() + ggplot2::scale_y_discrete(expand = c(0, 0)) + ggplot2::geom_vline( ggplot2::aes(xintercept = mean(unlist(data["values"]))), @@ -898,7 +922,6 @@ make_baseplot <- function(spe, df, to_plot, palette = "Mako", transform_scale = size = 1 ) + ggplot2::theme_classic() + - # ggplot2::ylim(c(0, 1000)) + ggplot2::theme( legend.position = "none", axis.text.y = ggplot2::element_blank(), @@ -907,15 +930,13 @@ make_baseplot <- function(spe, df, to_plot, palette = "Mako", transform_scale = axis.title = ggplot2::element_blank(), axis.text.x = ggplot2::element_text(size = 14) ) - # ggplot2::ylim(0, max(data["values"])) - # cowplot::plot_grid(spatial, density) - plot <- ggpubr::ggarrange(p, density, ncol = 2, widths = c(2, 1)) # add functions to pkg.R - # plot <- grid::grid.draw(plot) # add functions to pkg.R + plot <- ggpubr::ggarrange(p, density_plot, ncol = 2, widths = c(2, 1)) } else { plot <- p } - ) + }) + if (save) { # check if provided path works diff --git a/vignettes/spacedeconv_data.Rmd b/vignettes/spacedeconv_data.Rmd index 31a4e87d..9483ba6b 100644 --- a/vignettes/spacedeconv_data.Rmd +++ b/vignettes/spacedeconv_data.Rmd @@ -69,6 +69,21 @@ Spatial data available as a Seurat Object can be converted into a SpatialExperim spe <- seurat_to_spatialexperiment(seurat_object) ``` +# VisiumHD Data + +For high-resolution VisiumHD data, the `VisiumIO` package provides functions to load and convert your data into a `SpatialExperiment` object. For additional information please check the VisiumIO [Documentation](https://github.com/waldronlab/VisiumIO). + +Below is an example of how to load VisiumHD data: + +```{r visiumHDData, eval=FALSE} +library(VisiumIO) +tenxData <- TENxVisiumHD( + spacerangerOut = "path/to/VisiumHD/data", + bin_size = "016" +) +spe <- import(tenxData) +``` + # Normalization SpaceDeconv offers an additional function for convenient normalization of SpatialExperiments. The normalization is saved in a new assay, so make sure the correct data is used during deconvolution by providing the desired assay with the parameters `assay_sc` and `assay_sp`. As normalization method `cpm` and `logcpm` are available. From 3fec774e7d128bde0b99e1cd670c8c5c0d04c823 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2025 09:11:58 +0000 Subject: [PATCH 2/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- R/visualization.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/R/visualization.R b/R/visualization.R index 9fc4ee4a..71d73cc0 100644 --- a/R/visualization.R +++ b/R/visualization.R @@ -797,13 +797,15 @@ make_baseplot <- function(spe, df, to_plot, palette = "Mako", transform_scale = p <- p + geom_sf(aes_string(fill = to_plot), lwd = 0, color = NA, data = sf_poly) } else if (spot_shape == "square") { p <- p + geom_tile(aes_string(x = "pxl_col_in_fullres", y = "pxl_row_in_fullres", fill = to_plot), - data = df, width = spot_distance, height = spot_distance) + data = df, width = spot_distance, height = spot_distance + ) } else if (spot_shape == "circle") { # For circles, we use geom_point with shape 21. # Here we approximate the circle size using spot_distance. The conversion factor may be adjusted. - circle_size <- spot_distance / 5 # Adjust this constant as needed. + circle_size <- spot_distance / 5 # Adjust this constant as needed. p <- p + geom_point(aes_string(x = "pxl_col_in_fullres", y = "pxl_row_in_fullres", fill = to_plot), - data = df, shape = 21, size = circle_size, stroke = 0) + data = df, shape = 21, size = circle_size, stroke = 0 + ) } else { stop("Invalid spot_shape. Allowed values are 'hexagon', 'square', or 'circle'.") } From d8ec20245ea19a9f1028f7c0937080f53e6646b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" Date: Wed, 5 Mar 2025 14:18:27 +0000 Subject: [PATCH 3/3] Roxygenize --- man/make_baseplot.Rd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/man/make_baseplot.Rd b/man/make_baseplot.Rd index b8edd929..d60ddf22 100644 --- a/man/make_baseplot.Rd +++ b/man/make_baseplot.Rd @@ -34,7 +34,8 @@ make_baseplot( show_legend = TRUE, nDigits = NULL, pseudocount = 1, - shift_positive = TRUE + shift_positive = TRUE, + spot_shape = "hexagon" ) } \arguments{