Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Showing R plots in Juno plot pane #333

Open
greimel opened this issue Aug 24, 2019 · 7 comments
Open

Showing R plots in Juno plot pane #333

greimel opened this issue Aug 24, 2019 · 7 comments
Labels

Comments

@greimel
Copy link
Contributor

greimel commented Aug 24, 2019

Is it possible to show ggplot2 plots in the Juno plot pane?

using RCall, DataFrames
@rlibrary ggplot2

df = DataFrame(x=rand(10), y=rand(10))
ggplot(df) + geom_point(aes(x=:x, y=:y))

This plot is shown in a Jupyter notebook, but when run in Juno, it is shown in an R plot window.

Instead of cross-posting in the Juno repo, I am pinging @pfitzseb. If you give me hints where to start this, I would try to tackle this myself.

@pfitzseb
Copy link

You need overloads for the correct Base.show method (see here for some docs on that). I didn't see any Base.show overloads in this package, so I have no idea how displaying stuff in Jupyter notebooks works.

@greimel
Copy link
Contributor Author

greimel commented Aug 24, 2019

thanks for the hint. I'll see how far I get.

As far as Juno is concerned, probably this: https://github.com/JuliaInterop/RCall.jl/blob/master/src/ijulia.jl

@greimel
Copy link
Contributor Author

greimel commented Aug 24, 2019

I think I got it to work.

using RCall, DataFrames
@rlibrary ggplot2

df_string = DataFrame(x = randn(100), y=randn(100), z1=rand(["a"; "b"], 100), z2=rand(["darkorange"; "lightblue"], 100))

plt = ggplot(df_string) + geom_point(aes(x=:x, y=:y, color=:z2)) # works with standard colors

using ImageShow
using FileIO
rdevicefun(m::MIME"image/png") = @rget png
#rdevicefun(m::MIME"image/svg+xml", f) = R"svg($f)"
ext(::MIME"image/png") = ".png"
#ext(::MIME"image/svg+xml") = ".svg"

function Base.show(io::IO, m::MIME"image/png", plt::RObject)
  f = tempname() * ext(m)
  width, height = get(io, :juno_plotsize, [100, 100])
  R"""
    png($f, width=$width, height=$height, units="px", pointsize=20)
    show($plt) # plot(rnorm(10), rnorm(10))
    dev.off()
   """
   show(io, m, load(f))
end

plt

Before I put this into a PR I need some advice

  • Is it a good idea to use use width, height = get(io, :juno_plotsize, [100, 100]) because the function might be useful outside Juno. Do you have suggestion for improvement?
  • Do you think the tmp-file is a good solution?
  • Since R plots are pointers, I couldn't figure out which type they actually are. Could someone tell be what I can use instead of ::RObject?

@pfitzseb
Copy link

Is it a good idea to use use width, height = get(io, :juno_plotsize, [100, 100]) because the function might be useful outside Juno. Do you have suggestion for improvement?

Would probably make sense to use the defaults that are already in place instead of [100, 100].

Do you think the tmp-file is a good solution?

Not really, but it might be the easiest solution for now (and is already what is used for IJulia display, so whatever).

Since R plots are pointers, I couldn't figure out which type they actually are. Could someone tell be what I can use instead of ::RObject?

You probably can't do any better, but for correctness you'll need to figure out a runtime check for whether you have a R-plot, and put that into

Base.showable(m::MIME"image/png", plt::RObject) = is_a_plot(plt)

so the display system does the right thing.

@greimel
Copy link
Contributor Author

greimel commented Aug 24, 2019

Thank you for your help!

Regarding

You probably can't do any better, but for correctness you'll need to figure out a runtime check for whether you have a R-plot, and put that into

Base.showable(m::MIME"image/png", plt::RObject) = is_a_plot(plt)

so the display system does the right thing.

probably some of the RCall contributors can help me out with this?

EDIT:

I found the is.ggplot() function in R. And it seems, that one cannot actually save a base plot and show it again.

So the code above actually doesn't work for base plots.

@greimel
Copy link
Contributor Author

greimel commented Aug 24, 2019

Now that I understand that R-base plots cannot be captured ex-post, I start to understand what the code in ijulia.jl does.

  1. It resets the default device so that plots are automatically saved to file
  2. At the end of each cell it checks if there is a plot open (post-execute hook)
  3. If there is a plot, show it, close the device and remove the file

Are there such things like post-execute hooks in Juno as well?

The two options I see are

  1. Use the current implementation for ggplot2 only
Base.showable(m::MIME"image/png", plt::RObject) = R"is.ggplot($plt)"
  1. Follow the IJulia strategy and implement post-execute hooks

@xgdgsc
Copy link

xgdgsc commented May 11, 2022

What could be done to show rcall plots in julia-vscode?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants