Skip to content

Commit

Permalink
Merge pull request #59 from jiajic/gg_image
Browse files Browse the repository at this point in the history
fix: rework image plotting
  • Loading branch information
jiajic authored Jan 26, 2024
2 parents be28444 + 7f2432c commit f58457c
Show file tree
Hide file tree
Showing 7 changed files with 869 additions and 843 deletions.
4 changes: 3 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: GiottoVisuals
Title: Visuals for the Giotto spatial biology analysis ecosystem
Version: 0.1.3
Version: 0.1.4
Authors@R: c(
person("Ruben", "Dries", email = "[email protected]",
role = c("aut", "cre")),
Expand Down Expand Up @@ -82,6 +82,8 @@ Collate:
'colorRamp2.R'
'color_palettes.R'
'dd.R'
'generics.R'
'gg_annotation_raster.R'
'gg_info_layers.R'
'globals.R'
'gstop.R'
Expand Down
6 changes: 5 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@

# GiottoVisuals 0.1.3 (2024/01/25)
# GiottoVisuals 0.1.4 (2024/01/25)
## bug fixes
- fix plotting color gradient when using param `point_shape = "no_border"`
- fix image NA value [#865](https://github.com/drieslab/Giotto/issues/865) by rbutleriii

## new
- `gg_annotation_raster()` internal generic for adding a `giottoImage`, `giottoLargeImage`, or `list` thereof to a `ggplot` object

# GiottoVisuals 0.1.2 (2023/01/12)

Expand Down
4 changes: 4 additions & 0 deletions R/generics.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

# internals
setOldClass("gg")
setGeneric("gg_annotation_raster", function(ggobj, gimage, ...) standardGeneric("gg_annotation_raster"))
113 changes: 113 additions & 0 deletions R/gg_annotation_raster.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@

#' @name gg_annotation_raster
#' @keywords internal
#' @title Append image to ggplot as annotation_raster
#' @param ggobj ggplot2 `gg` object
#' @param gimage `giottoLargeImage`, `giottoImage` or `list` thereof
#' @return `gg` object with images to plot appended as annotation rasters
NULL

#' @rdname gg_annotation_raster
setMethod(
"gg_annotation_raster",
signature(ggobj = "gg", gimage = "list"),
function(ggobj, gimage, ...)
{
for(i in seq_along(gimage)) {
ggobj <- gg_annotation_raster(ggobj, gimage[[i]], ...)
}
return(ggobj)
}
)

#' @rdname gg_annotation_raster
setMethod(
"gg_annotation_raster",
signature(ggobj = "gg", gimage = "giottoImage"),
function(ggobj, gimage, ...)
{
# extract min and max from object
my_xmax = gimage@minmax[1]
my_xmin = gimage@minmax[2]
my_ymax = gimage@minmax[3]
my_ymin = gimage@minmax[4]

# convert giotto image object into array
img_array = as.numeric(gimage@mg_object[[1]])

# extract adjustments from object
xmax_b = gimage@boundaries[1]
xmin_b = gimage@boundaries[2]
ymax_b = gimage@boundaries[3]
ymin_b = gimage@boundaries[4]

# append to ggobj
ggobj <- ggobj + annotation_raster(
img_array,
xmin = my_xmin-xmin_b, xmax = my_xmax+xmax_b,
ymin = my_ymin-ymin_b, ymax = my_ymax+ymax_b
)

# TODO geom_raster to accommodate single-channel
return(ggobj)
}
)

#' @rdname gg_annotation_raster
setMethod(
"gg_annotation_raster",
signature(ggobj = "gg", gimage = "giottoLargeImage"),
function(ggobj, gimage, ...)
{
# get plotting minmax
extent = terra::ext(gimage@raster_object)[1:4]
xmin = extent[['xmin']]
xmax = extent[['xmax']]
ymin = extent[['ymin']]
ymax = extent[['ymax']]

# convert raster object into array with 3 channels
img_array = terra::as.array(gimage@raster_object)

# TODO: check if required, fixes NaN values
# replacing NA's by zero or another value directly in raster object?
# raster[is.na(raster[])] <- 0
if (is.nan(max(img_array[,,1]))) {
img_array[,,1][is.nan(img_array[,,1])] = max(img_array[,,1], na.rm = TRUE)
}

if(dim(img_array)[3] > 1) {
if(is.nan(max(img_array[,,2]))) {
img_array[,,2][is.nan(img_array[,,2])] = max(img_array[,,2], na.rm = TRUE)
}
}

if(dim(img_array)[3] > 2) {
if(is.nan(max(img_array[,,3]))) {
img_array[,,3][is.nan(img_array[,,3])] = max(img_array[,,3], na.rm = TRUE)
}
}

img_array = img_array/max(img_array, na.rm = TRUE)
if(dim(img_array)[3] == 1) {
img_array_RGB = array(NA, dim = c(dim(img_array)[1:2],3))
img_array_RGB[,,1:3] = img_array
} else {
img_array_RGB = img_array
}

# handle NA values
img_array_RGB[is.na(img_array_RGB)] <- 0

# append to ggobj
ggobj <- ggobj + annotation_raster(
img_array_RGB,
xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax
)

# TODO geom_raster to accommodate single-channel
return(ggobj)
}
)

146 changes: 2 additions & 144 deletions R/gg_info_layers.R
Original file line number Diff line number Diff line change
Expand Up @@ -1350,151 +1350,9 @@ plot_spat_image_layer_ggplot = function(gg_obj,
# Assign region to plot
gg_obj = gg_obj + geom_blank(data = spat_ext, aes_string(sdimx, sdimy))

if((inherits(gimage, 'list') | is.vector(gimage)) & length(gimage) > 1) {

for(i in 1:length(gimage)) {

if(inherits(gimage[[i]], 'giottoImage')) {
# extract min and max from object
my_xmax = gimage[[i]]@minmax[1]
my_xmin = gimage[[i]]@minmax[2]
my_ymax = gimage[[i]]@minmax[3]
my_ymin = gimage[[i]]@minmax[4]

# convert giotto image object into array
img_array = as.numeric(gimage[[i]]@mg_object[[1]])

# extract adjustments from object
xmax_b = gimage[[i]]@boundaries[1]
xmin_b = gimage[[i]]@boundaries[2]
ymax_b = gimage[[i]]@boundaries[3]
ymin_b = gimage[[i]]@boundaries[4]

gg_obj = gg_obj + annotation_raster(img_array,
xmin = my_xmin-xmin_b, xmax = my_xmax+xmax_b,
ymin = my_ymin-ymin_b, ymax = my_ymax+ymax_b)

# TODO geom_raster to accommodate single-channel

} else if(inherits(gimage[[i]], 'giottoLargeImage')) {
# get plotting minmax
extent = terra::ext(gimage[[i]]@raster_object)[1:4]
xmin = extent[['xmin']]
xmax = extent[['xmax']]
ymin = extent[['ymin']]
ymax = extent[['ymax']]

# convert raster object into array with 3 channels
img_array = terra::as.array(gimage[[i]]@raster_object)

# TODO: check if required, fixes NaN values
# replacing NA's by zero or another value directly in raster object?
# raster[is.na(raster[])] <- 0
if(is.nan(max(img_array[,,1]))) {
img_array[,,1][is.nan(img_array[,,1])] = max(img_array[,,1], na.rm = T)
}

if(dim(img_array)[3] > 1) {
if(is.nan(max(img_array[,,2]))) {
img_array[,,2][is.nan(img_array[,,2])] = max(img_array[,,2], na.rm = T)
}
}

if(dim(img_array)[3] > 2) {
if(is.nan(max(img_array[,,3]))) {
img_array[,,3][is.nan(img_array[,,3])] = max(img_array[,,3], na.rm = T)
}
}



# Assign image(s) to plot
gg_obj <- gg_annotation_raster(ggobj = gg_obj, gimage = gimage)

img_array = img_array/max(img_array, na.rm = TRUE)
if(dim(img_array)[3] == 1) {
img_array_RGB = array(NA, dim = c(dim(img_array)[1:2],3))
img_array_RGB[,,1:3] = img_array
img_array_RGB[is.na(img_array_RGB)] = 0
} else {
img_array_RGB = img_array
}

gg_obj = gg_obj + annotation_raster(img_array_RGB,
xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax)

# TODO geom_raster to accommodate single-channel
}

}

} else {

if(methods::is(gimage, 'giottoImage')) {
# extract min and max from object
my_xmax = gimage@minmax[1]
my_xmin = gimage@minmax[2]
my_ymax = gimage@minmax[3]
my_ymin = gimage@minmax[4]

# convert giotto image object into array
img_array = as.numeric(gimage@mg_object[[1]])

# extract adjustments from object
xmax_b = gimage@boundaries[1]
xmin_b = gimage@boundaries[2]
ymax_b = gimage@boundaries[3]
ymin_b = gimage@boundaries[4]

gg_obj = gg_obj + annotation_raster(img_array,
xmin = my_xmin-xmin_b, xmax = my_xmax+xmax_b,
ymin = my_ymin-ymin_b, ymax = my_ymax+ymax_b)

} else if(methods::is(gimage, 'giottoLargeImage')) {
# get plotting minmax
extent = terra::ext(gimage@raster_object)[1:4]
xmin = extent[['xmin']]
xmax = extent[['xmax']]
ymin = extent[['ymin']]
ymax = extent[['ymax']]

# convert raster object into array with 3 channels
img_array = terra::as.array(gimage@raster_object)

# TODO: check if required, fixes NaN values
# replacing NA's by zero or another value directy in raster object?
# raster[is.na(raster[])] <- 0
if(is.nan(max(img_array[,,1]))) {
img_array[,,1][is.nan(img_array[,,1])] = max(img_array[,,1], na.rm = T)
}

if(dim(img_array)[3] > 1) {
if(is.nan(max(img_array[,,2]))) {
img_array[,,2][is.nan(img_array[,,2])] = max(img_array[,,2], na.rm = T)
}
}

if(dim(img_array)[3] > 2) {
if(is.nan(max(img_array[,,3]))) {
img_array[,,3][is.nan(img_array[,,3])] = max(img_array[,,3], na.rm = T)
}
}

img_array = img_array/max(img_array, na.rm = TRUE)
if(dim(img_array)[3] == 1) {
img_array_RGB = array(NA, dim = c(dim(img_array)[1:2],3))
img_array_RGB[,,1:3] = img_array
img_array_RGB[is.na(img_array_RGB)] = 0
} else {
img_array_RGB = img_array
}

gg_obj <- gg_obj +
annotation_raster(img_array_RGB,
xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax)
}

}

if(!is.null(spatlocs)) {
gg_obj <- gg_obj +
Expand Down
Loading

0 comments on commit f58457c

Please sign in to comment.