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

better support for Plotly renderers #1540

Open
cderv opened this issue Feb 28, 2024 · 1 comment
Open

better support for Plotly renderers #1540

cderv opened this issue Feb 28, 2024 · 1 comment

Comments

@cderv
Copy link
Contributor

cderv commented Feb 28, 2024

This is the result of an investigation for

Context

Plotly in python offers some renderers configurations : https://plotly.com/python/renderers/#interactive-renderers

In Quarto we do some adjustment in Jupyter context - by default we set notebook_connected, unless in format: dashboard where we use notebook by default. We then handle the dependencies, and add possibly missing require.js and jQuery

It happens that there is some difference when using reticulate and plotly in Dashboard with Jupyter engine and plotly. So I looked into it to understand.

This raises some questions.

reticulate behavior.

I was curious of which renderers was used in reticulate context. Quarto does not do anything for R on this.

I saw that reticulate is setting a default if none set

reticulate/R/knitr-engine.R

Lines 567 to 576 in b1c33d5

# override the figure 'show' method to just return the plot object itself
# the auto-printer will then handle rendering the image as appropriate
io <- import("plotly.io", convert = FALSE)
io$show <- function(self, ...) self
renderers <- io$renderers
if (!py_bool(renderers$default))
renderers$default <- "plotly_mimetype+notebook"
}

Though from some test, I don't think this is applied. It seems browser is the default one.

---
title: "Test"
output: 
  html_document:
    self_contained: false
    keep_md: true
---

```{r}
library(reticulate)
```

# Page 1

```{python}
import plotly.graph_objects as go
import plotly.io as pio
pio.renderers
```

```{python}
fig = go.Figure()

fig=fig.add_trace(
    go.Scatter(
        x=[1, 2, 3],
        y=[1, 3, 1]))

fig.show()

```

image

Changing the value of this to something like notebook_connected for example, does not work.

```{python}
import plotly.graph_objects as go
import plotly.io as pio
pio.renderers.default = "notebook" # or "notebook_connected"
pio.renderers
```

Plots does not show. Because plotly.js is not included. This includes also setting to the supposed default plotly_mimetype+notebook

So I looked at how the plotly output and dependencies are handled in reticulate
This goes in there

reticulate/R/knitr-engine.R

Lines 710 to 716 in b1c33d5

} else if (isHtml && py_has_method(value, "_repr_html_")) {
py_capture_output({
data <- as_r_value(value$`_repr_html_`())
})
.engine_context$pending_plots$push(knitr::raw_html(data))
return("")

Looking at the intermediate .md file, I noticed that the plotly js deps was not included in the raw block created. And it is not included as HTML dependencies in includes.

So somehow, it is not catched.

Looking in debug mode, this is what I noticed in such mode plotly_mimetype+notebook. I believe the dependency is something printed as stdout and captured - which is currently un-used.
I did the following at the breakpoint at code above

capt <- py_capture_output({
    data <- as_r_value(value$`_repr_html_`())
})

and then

  • data is only the <div> with the id that a script fills

    > xml2::xml_structure(xml2::read_xml(data))
    <div>
      <div [id, class, style]>
      <script [type]>
        {text}
  • the dependency happens to be in capt, so the captured output as a JSON

> substr(capt, 1, 100)
[1] "{'text/html': '        <script type=\"text/javascript\">\\n        window.PlotlyConfig = {MathJaxConfig"

I don't know if notebook is really supposed to work with reticulate and if it is required to make it works, but this raises question on plotly handling to me in knitting context.

We should be able to catch dependencies and includes it as knit_meta like others. I don't know if browser renderers is a good default also (or an expected default).

Happy to discuss and work on something. I believe there needs to be some adaptation for correct rendering in Quarto context.

@t-kalinowski
Copy link
Member

If I recall correctly, I started setting a default renderer specifically for CI---on Ubuntu running in headless mode on GHA runners, the default render would be unset, result in an error. As far as I know, this was never a user issue, just our own CI that was failing.

I'm happy to make any changes you recommend! At this point you're more familiar with plotly internals, and any second order effects in quarto or rmarkdown that changes to this code might have. Suggestions welcome :)

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

No branches or pull requests

2 participants