quarto-dev / quarto-cli

Open-source scientific and technical publishing system built on Pandoc.
https://quarto.org
Other
3.7k stars 300 forks source link

rgl plots don't display in quarto #1800

Closed dmurdoch closed 2 years ago

dmurdoch commented 2 years ago

rgl plots work in RMarkdown using several low level hooks that are set up by the rgl::setupKnitr() function. This doesn't work in quarto, presumably because things are implemented differently, though other htmlwidgets-using packages (e.g. leaflet) work fine.

I'm not sure if this requires changes to rgl, to quarto, or to both.

I've also started an rgl issue.

Here's a sample RMarkdown document:

---
title: "Untitled"
output: html_document
---

```{r}
library(rgl)
setupKnitr(autoprint = TRUE)
plot3d(1:10, 1:10, 1:10)

Here's the same thing as a Quarto document:

title: "Untitled" format: html editor: visual

This normally wouldn't be echoed:

library(rgl)
setupKnitr(autoprint = TRUE)

rgl doesn't display:

plot3d(1:10, 1:10, 1:10)
cscheid commented 2 years ago

Maybe a place to start is for you to see if there's a difference between leaflet and rgl's setup.

dmurdoch commented 2 years ago

Yes, there certainly is, because rgl tries to emulate base graphics (i.e. minor changes should be ignored, only major changes should be displayed).

dmurdoch commented 2 years ago

The biggest difference I've found so far is printing methods(knitr::sew): in RMarkdown, this prints

methods(knitr::sew)

##  [1] sew.character*        sew.default*          sew.error*           
##  [4] sew.html_screenshot*  sew.knit_asis*        sew.knit_embed_url*  
##  [7] sew.knit_image_paths* sew.list*             sew.message*         
## [10] sew.recordedplot*     sew.rglRecordedplot*  sew.rlang_error*     
## [13] sew.source*           sew.warning*         
## see '?methods' for accessing help and source code

and rgl reliies on it to display the plot. In Quarto, I see

methods(knitr::sew)

no methods found

In knitr, display of graphics happens in two steps. The second step is called sew, but it looks like Quarto isn't using that. Can you point me to how Quarto does printing?

dmurdoch commented 2 years ago

I think the issue might lie in this code that patches knitr::sew with a non-generic function:

https://github.com/quarto-dev/quarto-cli/blob/33d62e153c9c88abfc78f5c6c9cdcca1dd437cf2/src/resources/rmd/patch.R#L146-L171

The result of knit_print on the graph to print from rgl should have class c("rglRecordedplot", "knit_other_plot"), neither of which is in the list of specified classes, so I believe this should fall through to the call to knitr_sew, the saved copy of knitr::sew before patching. However, somehow the methods table has been messed up as shown in my previous comment, so it doesn't get dispatched.

jjallaire commented 2 years ago

Hi @dmurdoch, just a note that we are doing this so that we can provide a more predictable markdown AST for downstream filters (e.g. enclosing things in the correct div structure). If you want to play with other variations of patching / dispatching to knitr::sew() then it is very easy to install the development version of Quarto, after which time you can just hack on patch.R without any rebuild.

To install the dev version: https://github.com/quarto-dev/quarto-cli#development-version

You may need to add quarto-cli/package/dist/bin to your path to make sure that the dev version is picked up by default. You can confirm you are running the dev version with:

$ quarto --version

Which should be 99.9.9

I'm also happy to hack on this with some guidance from you (i.e. more directed speculation as to what sort of change would get rgl working and preserve our override). I note that in the comments we have some code that works around limitations in R 3.4 -- I think we could probably drop this at this point if need be.

Note also that changes in knitr could resolve this (and mitigrate the need to do any patching) but we generally don't want to depend on the very latest version of knitr.

dmurdoch commented 2 years ago

@jjallaire, thanks for the dev install instructions. I'll try that and see if I can figure out what's going on.

jjallaire commented 2 years ago

When working on the R code its hard (impossible?) to hit a breakpoint b/c the R code is run from Quarto not from the current R session. I typically just use calls to str() to figure out what's going on (and note again that as soon as you make a change to patch.R it will be available, no need to restart preview or do any build or configure)

jjallaire commented 2 years ago

I'm not seeing the scroll bar you mention. One thing we do with htmlwidgets in Quarto is that if they mark themselves as "knitr figures" (i.e. respecting fig.width and fig.height) then we attempt to make them responsive to the width of the body column by setting width=100% (which should at a minimum avoid horizontal scrollbars). Here is what I see on OS X w/ Chrome:

Screen Shot 2022-08-13 at 1 45 27 PM

Perhaps there is another example that will exhibit the scroll bars? If so LMK and I can suggest an approach to work around this.

jjallaire commented 2 years ago

Re-opening pending resolution of the scrollbar issue.

dmurdoch commented 2 years ago

I'm not sure what's going on with the scrollbars. The initial display I see in Firefox has both showing. In Chrome I only get one, as in the attached screenshot Screen Shot 2022-08-13 at 3 25 00 PM .

jjallaire commented 2 years ago

Okay, I did indeed observed the scrollbar in Firefox.

We set overflow-x: auto on output divs (e.g. so that wide tables can scroll horizontally). I think this CSS is giving canvas some trouble so I just trigger an opt-out for overflow-x when I see an RGL widget (we already had this implemented for shiny select inputs): https://github.com/quarto-dev/quarto-cli/commit/0e49ed4473de3ecd564886c5704dab5427f02644

dmurdoch commented 2 years ago

Thanks, looks great now.