Closed Yunuuuu closed 1 month ago
I'm not sure what you mean with 'incorporate the ggplot_build()
method, would you mind clarifying a bit?
Something like this, other objects can utilize ggplot_build
methods to use ggsave
seamlessly.
ggsave <- function(filename, plot) {
# before drawing, call `ggplot_build` or maybe `ggplotGrob`
plot <- ggplot_build(plot)
# ... here we do some other common work
grid.draw(plot)
invisible(filename)
}
Implicitly, it is used in the grid.draw.ggplot()
method for typical ggplots. This should work fine for any subclass of ggplot.
If you have a plot with a different class, you should make a grid.draw.your_class()
method that renders the plot. I don't think ggplot2 should change anything here.
Also, based on the error message, it seems like your class object doesn't have a theme
element that is required for rendering a typical ggplot.
@Yunuuuu
In my understanding, it's your responsibility to make your ggheatmap object compatible with ggplot2. While you might be able to bypass the error by asking for a tweak in this specific case of ggsave()
, but I'm afraid you'll encounter various errors on the functions that assume the input is an ordinary ggplot object. It's not realistic to ask the authors to modify their functions, especially it's an extension package.
I think it's a good attempt to utilize S4 system to overcome the limitation of S3, although I'm not sure whether it will succeed or not in the end. I'm not familiar with S4, but maybe you can override $
better?
library(ggheat)
#> Loading required package: ggplot2
p1 <- ggplot()
p1$theme
#> list()
p2 <- ggheat(matrix())
p2$theme
#> Error in slot(x, name): no slot of name "theme" for this object of class "ggheatmap"
Created on 2024-07-17 with reprex v2.1.0
@teunbrand
Implicitly, it is used in the
grid.draw.ggplot()
method for typical ggplots.
To be clear, the error happens before grid.draw()
.
https://github.com/tidyverse/ggplot2/blob/25ad0b17865c1280c464ccfbee38c3d7eb5df95d/R/save.R#L106
Thanks for your suggestion, @yutannihilation. It is not possible for ggheat
to know the value of plot.background
before it is built into a patchwork
object, as the elements are simply a list of ggplot objects. However, I have found a solution by creating a custom method for the $
operator with a specific consideration for ggplot2
. Here is an example of how it can be done in R:
#' Subset a `ggheatmap` object
#'
#' Used by [ggplot_build][ggplot2::ggplot_build]
#'
#' @param x A ggheatmap object
#' @param name A string of slot name in `ggheatmap` object.
#' @keywords internal
methods::setMethod("$", "ggheatmap", function(x, name) {
if (name == "theme") {
slot(x, "heatmap")$theme
} else if (name == "plot_env") {
slot(x, "plot_env")
} else {
cli::cli_abort(c(
"`$` is just for internal usage for ggplot2 methods",
i = "try to use `@` method instead"
))
}
})
I have implemented another S4 class to override the +.gg
method, as suggested by @teunbrand you. This approach was recommended in your previous interaction in stackoverflow
, which can be found here: stackoverflow.com/questions/65817557/s3-methods-extending-ggplot2-gg-function. Initially, I tried using an S3 class and adding a gg
element to the ggheat
object. However, there was a conflict between the +.ggheat
method and the +.gg
method. In order to resolve this conflict, I decided to utilize an S4 class instead. I am pleased to report that the implementation is now functioning smoothly and is capable of performing all the tasks of Complexheatmap
.
By using the tricks in https://github.com/tidyverse/ggplot2/issues/6002#issuecomment-2233743223, I'm able to resolve the problem when using ggsave
in ggheat package. It's well for me to close this issue. Thanks.
Hi, is it possible to let
ggsave
utilizeggplot_build
method? in this way, all objects supportggplot_build
can useggsave
functionI have developed a ggplot2 extension ggheat for creating heatmaps and I would like to utilize all the functions in ggplot, including
ggsave
. However, creating a new function with the same name would result in duplication. Additionally, since the package automatically loads ggplot, there is no need to create a duplicate function. Tt would be beneficial to incorporate theggplot_build
method, and it would make ggplot extension more powerful and allow for seamless integration with the existing ggplot function.Created on 2024-07-17 with reprex v2.1.0 ~