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

Plots not shown in HTML export for default Plotly renderer #6999

Closed
jackthepanisher opened this issue Aug 7, 2021 · 22 comments
Closed

Plots not shown in HTML export for default Plotly renderer #6999

jackthepanisher opened this issue Aug 7, 2021 · 22 comments
Labels
bug Issue identified by VS Code Team member as probable bug notebook-import-export notebook-workflow Issues that interrupt expected or desirable behavior

Comments

@jackthepanisher
Copy link

Environment data

  • VS Code version: 1.59.0
  • Jupyter Extension version (available under the Extensions sidebar): v2021.8.1195043623
  • Python Extension version (available under the Extensions sidebar): v2021.8.1105858891
  • OS (Windows | Mac | Linux distro) and version: Windows 10 20H2
  • Python and/or Anaconda version: 3.9.5
  • Type of virtual environment used (N/A | venv | virtualenv | conda | ...): NA
  • Jupyter server running: Local

Expected behaviour

Plots are visible when exporting to HTML

Actual behaviour

Plots are not shown (and there is no track of it in the HTML source code)

Steps to reproduce:

import plotly.express as px
fig = px.scatter(x=[0, 1, 2, 3, 4], y=[0, 1, 4, 9, 16])
fig.show()

The temporary notebook for exporting (%localappdata%\temp<UUID>\export.ipynb) already misses the expected output.

Switching the Plotly renderer to notebook using fig.show(renderer='notebook') provides the expected plot output in the exported HTML

On a side note, the iframe / iframe_connected renderer types don't produce any plot output in VS Code but the export to HTML works as expected. It seems that iframes are not working/are not supported in VS Code right now (it has worked a while back) - maybe worth another bug entry.

Export to PDF probably has the same issue - not checked.

Logs

Output for Jupyter in the Output panel (ViewOutput, change the drop-down the upper-right of the Output panel to Jupyter)

XXX

@jackthepanisher jackthepanisher added the bug Issue identified by VS Code Team member as probable bug label Aug 7, 2021
@joyceerhl
Copy link
Contributor

@jackthepanisher Is this export to HTML from the interactive window or from a notebook?

@joyceerhl joyceerhl added the info-needed Issue requires more information from poster label Aug 9, 2021
@jackthepanisher
Copy link
Author

jackthepanisher commented Aug 10, 2021

@jackthepanisher Is this export to HTML from the interactive window or from a notebook?

@joyceerhl the behavior is the same for notebook and interactive window. I can also mix multiple fig.show(renderer='vscode') and fig.show(renderer='notebook') statements where plots are shown for both cases in the notebook/interactive window but only the renderer='notebook' one shows up in the HTML export.

Note: fig.show(renderer='vscode') is the default setting in VS Code i.e. same as fig.show()

@joyceerhl
Copy link
Contributor

Thanks for the answer, I can reproduce the problem.

@joyceerhl joyceerhl removed the info-needed Issue requires more information from poster label Aug 10, 2021
@joyceerhl
Copy link
Contributor

I am seeing that the plots are persisted to disk in the ipynb file, so they're getting omitted from the generated html during the nbconvert process.

@joyceerhl joyceerhl removed their assignment Aug 10, 2021
@jackthepanisher
Copy link
Author

Opening the notebook on the Jupyter server directly (python -m notebook <file>.ipynb) also does not show the plot output with the vscode renderer. Re-running the affected cell there does not help either. It seems that is a general issue with the mime type renderers (vscode is an alias of that in Plotly). I'm wondering what the actual benefit of the mime typer renderer is compared to the notebook renderer.

@jackthepanisher
Copy link
Author

Well, I tried to load the notebook also with JupyterLab. There the vscode aka plotly_mimetype does show up but the notebook one does not. So maybe that is expected for classical notebook server vs. JupyterLab. However, when exporting the notebook from JupyterLab to HTML, the vscode/plotly_mimetype one shows up as static image and the notebook one also shows up as an interactive graph.

I guess the expectation for VS Code is to have an output produced in some way for the default renderer, even if it is a static image. If producing an interactive graph for the HTML export is a limitation of the mime type renderer in general, I would really like to switch to the notebook renderer instead, as I've experienced better results and behavior with it. Currently, issue #6404 is some remaining piece for me to switch to the notebook renderer entirely.

@jackthepanisher
Copy link
Author

Running nbconvert directly using py -m jupyter nbconvert notebook.ipynb --to html --output notebook.html reveals:

..\nbconvert\filters\datatypefilter.py:39: UserWarning: Your element with mimetype(s) dict_keys(['application/vnd.plotly.v1+json']) is not able to be represented.
  warn("Your element with mimetype(s) {mimetypes}"

It looks like nbconvert doesn't like the Plotly mime type + json format that is generated with renderer='vscode'. There are some tracks of it in jupyter/nbconvert#944. JupyterLab appears to use a Plotly extension to convert the mime type to static images. Not sure if VS Code should support something similar. Right now the notebook renderer(s) seem to provide the only option to export Plotly graphs to HTML from within VS Code.

@DavidKutu DavidKutu added this to the September 2021 milestone Aug 31, 2021
@greazer greazer removed this from the September 2021 milestone Sep 2, 2021
@congyiwu
Copy link

congyiwu commented Sep 22, 2021

The best (EDIT: another) workaround I've found is to enable multiple renders in Plotly. With the snippet below, I see a single interactive plot in both the VS Code UI and exported HTML.

  • The Plotly docs suggest that enabling multiple renderers is the intended solution, although it would be nice if it just magically worked by default.
  • The main downside (if you commit ipynb files to Git) is probably that this bloats the ipynb file, but I'm using the Jupytext for Notebooks VS Code extension to automatically strip outputs.
    • Actually I'm using a fork ofteh extension with some tweaks I'm trying to upstream.
import plotly.express as px
import plotly.io as pio

# This ensures Plotly output works in multiple places:
# plotly_mimetype: VS Code notebook UI
# notebook: "Jupyter: Export to HTML" command in VS Code
# See https://plotly.com/python/renderers/#multiple-renderers
pio.renderers.default = "plotly_mimetype+notebook"

fig = px.line(...)
fig.show()

@congyiwu
Copy link

Hmm, it turns out I see output in both places w/ just the "notebook renderer":

pio.renderers.default = "notebook"
  • With plotly_mimetype+notebook, VS Code does seem to use plotly_mimetype, since when I click "Choose output mimetype" from the top-left corner menu for my plot, it shows application/vnd.plotly.v1+json as active, and text/html as a separate option
  • With notebook, it only shows text/html
  • I don't know if there's any benefit in practice to using multiple renders...

@jackthepanisher
Copy link
Author

@congyiwu thanks for providing another workaround using multiple renderers. I already mentioned using just the notebook renderer in the first post but this has some other drawbacks like re-opening will currently not show plots rendered with the notebook renderer (see issue #6404). So using multiple renderers might be a better workaround until this is fixed.

@LY1806620741
Copy link

I get the same problem. My ipynb output a object type <IPython.core.display.HTML object>. Then It don't render in view. And Test Normal on jupyter-notebook server.

@DonJayamanne DonJayamanne added issue_grooming_don notebook-workflow Issues that interrupt expected or desirable behavior and removed issue_grooming_don notebook-import-export labels Oct 18, 2021
@DonJayamanne
Copy link
Contributor

This isn't an issue with import/export, i.e. there's nothing wrong with our import export code.
The problem is with the mime types generated by polotly (outputs).

To me this is an nb-golden, the notebook cannot be saved as HTML, we might want to find the exact cause and notify plotly/nbconvert about this.

Possible they area aware of this, but we don't seem to know what's going on and i think we should update this issue accordingly.

@greazer
Copy link
Member

greazer commented Oct 21, 2021

Per @DonJayamanne, this issue is not one we can resolve within the Jupyter extension.

@greazer greazer closed this as completed Oct 21, 2021
@ronglums
Copy link
Contributor

talked to @greazer. Another customer ran into this. Is this something we can do in the Jupyter extension to make it just work out of box?

@DonJayamanne
Copy link
Contributor

DonJayamanne commented Feb 21, 2022

Note:

  • I just installed the plotly package and the default mime is plotly_mimetype+notebook
  • Tested in Jupyter & Jupyter Lab (export works and default mime is the same as above)
  • Also tested this in VS Code and seems to work.

I think the changes in the default mime type to plotly_mimetype+notebook by Plotly folk is what makes this work now.

Based on previous comments it seems this wasn't the default mime type in Plotly package, see here #6999 (comment), #6999 (comment)

Users with the new plotly versions might not have issues (at least I don't) , and users with older versions might have issues (which could be whats going on here).

We could optionally update the startup commands to change the defaults.

Suggestion:

  • When user hits the export button, we can let them know that the defaults need to be changed and they need to re-run the cells.
  • Asking users to change this before export (when running cells is borderline spamming with prompts) and updating without asking the user isn't right either.
  • As this is a problem with the plotly package i propose we prompt after the user hits the export button.

@jackthepanisher
Copy link
Author

If Plotly runs in VS Code env, the renderer will default to vscode (see _renderers.py#L489-L491). It will default to plotly_mimetype+notebook only if the specific environment is not handled or there is already a default renderer set.

If VS Code\Jupyter wants to go the route of plotly_mimetype+notebook, it might be desirable to just remove the special handling in Plotly for VS Code. Or alternatively, add the notebook renderer to the existing vscode default (in Plotly).

Another note is that plotly_mimetype+notebook will produce the mimetype data as well as text/html for all Plotly cell outputs in the .ipynb file. Jupter files will get slightly bigger with this. However, it doesn't seem to lead to multiple inclusion of plotly.js. The HTML exports will not change in size as just the notebook renderer applies.

@mikayla-eckelcifrese
Copy link

The best (EDIT: another) workaround I've found is to enable multiple renders in Plotly. With the snippet below, I see a single interactive plot in both the VS Code UI and exported HTML.

  • The Plotly docs suggest that enabling multiple renderers is the intended solution, although it would be nice if it just magically worked by default.

  • The main downside (if you commit ipynb files to Git) is probably that this bloats the ipynb file, but I'm using the Jupytext for Notebooks VS Code extension to automatically strip outputs.

    • Actually I'm using a fork ofteh extension with some tweaks I'm trying to upstream.
import plotly.express as px
import plotly.io as pio

# This ensures Plotly output works in multiple places:
# plotly_mimetype: VS Code notebook UI
# notebook: "Jupyter: Export to HTML" command in VS Code
# See https://plotly.com/python/renderers/#multiple-renderers
pio.renderers.default = "plotly_mimetype+notebook"

fig = px.line(...)
fig.show()

Thank you SO MUCH for this!

@DonJayamanne
Copy link
Contributor

Closing this as an upstream issue, unfortunately there's nothing mujch we can do here, the generated mime types from the plotly package needs to contain text/html as well.

Issue is here plotly/plotly.py#3977

@jackthepanisher
Copy link
Author

@DonJayamanne, although there are some workarounds available VS Code could be a bit more verbose when handling such case. Currently, there is no indication to the user that the HTML export is failing to produce the graphs with the default settings.

Without any specific renderer specified, VS Code uses the default Plotly renderer set to vscode aka plotly_mimetype. JupyterLab uses plotly_mimetype+notebook. The latter allows for exporting interactive Plotly graphs to HTML but in general increases the size of all .ipynb files with that setting. One can configure the default renderer or on-demand renderer to the same or vscode+notebook to get the same results in VS Code. So this seems to be a valid workaround to use with the mentioned drawback of increased file sizes (one could also use notebook_connected for a reduced file size but required internet connectivity upon HTML display).

The difference to JupyterLab is that even with the renderer set to vscode aka plotly_mimetype, exporting such notebook in JupyterLab will produce a static picture and not only an empty cell as with VS Code. Not sure if this is specific or a default behavior with JupyerLab.

Furthermore, converting a notebook with nbconvert using vscode / plotly_mimetype will produce the following warning:

UserWarning: Your element with mimetype(s) dict_keys(['application/vnd.plotly.v1+json']) is not able to be represented.

It would be good if VS Code could produce a similar warning, if possbile, when trying to export application/vnd.plotly.v1+json content to HTML. Exporting to a static picture would of course be even more convenient.

For completeness, another method for exporting is to use nbconvert and set the PLOTLY_RENDERER environment variable to a supported renderer method like notebook. This requires to not change the default renderer or use on-demand renderer settings in the ipynb notebook file:

$env:PLOTLY_RENDERER='notebook'; python -m nbconvert .\my_notebook.ipynb --to html --execute; Remove-Item Env:\PLOTLY_RENDERER

@DonJayamanne
Copy link
Contributor

DonJayamanne commented Dec 7, 2022

there is no indication to the user that the HTML export is failing to produce the graphs with the default settings.

I don't think we need special cases for plotly, if there is no HTML output i don't think we should make any assumptions and warn or display messages to a user or in the logs. Because if the user ran nbconvert they'd get the exact same results.

VS Code uses the default Plotly renderer set to vscode aka plotly_mimetype. JupyterLab uses plotly_mimetype+notebook.

this is not true. VS Code doesn't change how plotly generates outputs. Its the plotly package that produces the different mime types, not vscode. Hence the reason for filing an issue upstream.

It would be good if VS Code could produce a similar warning, if possbile, when trying to export application/vnd.plotly.v1+json content to HTML. Exporting to a static picture would of course be even more convenient.

Agreed, will file an issue for this.

. This requires to not change the default renderer or use on-demand renderer settings in the ipynb notebook file:

However this ends up running the whole notebook all over again. I don't thiknk this is a good thing. What if notebook,s end up having code that modify state on disc or the like. Also exports could take a long time.
If anything this should be an option for the user.

@jackthepanisher
Copy link
Author

there is no indication to the user that the HTML export is failing to produce the graphs with the default settings.

I don't think we need special cases for plotly, if there is no HTML output i don't think we should make any assumptions and warn or display messages to a user or in the logs. Because if the user ran nbconvert they'd get the exact same results.

Agreed. Having the error/warning bubble up from nbconvert should be sufficient.

VS Code uses the default Plotly renderer set to vscode aka plotly_mimetype. JupyterLab uses plotly_mimetype+notebook.

this is not true. VS Code doesn't change how plotly generates outputs. Its the plotly package that produces the different mime types, not vscode. Hence the reason for filing an issue upstream.

Correct. Sorry for the confusion. It's Plotly's setting that is set according to the detected environment. I also don't like the 'vscode+notebook' workaround as it produces bigger notebook files only to be able to export to HTML which is probably not used that frequently.

This requires to not change the default renderer or use on-demand renderer settings in the ipynb notebook file:

However this ends up running the whole notebook all over again. I don't thiknk this is a good thing. What if notebook,s end up having code that modify state on disc or the like. Also exports could take a long time.
If anything this should be an option for the user.

Yes, this was more meant to be a manual workaround not to be part of any VS Code workflow.

@jrdalenberg
Copy link

but only the renderer='notebook' one shows up in the HTML export.

Oh, wow, thanks @jackthepanisher! I was breaking my head for many hours to figure out how I could export an interactive time series plot to HTML. I finally got it working with that renderer. I also could not figure it out with matplotlib widgets, which resulted in static images inside the HTML page.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 7, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue identified by VS Code Team member as probable bug notebook-import-export notebook-workflow Issues that interrupt expected or desirable behavior
Projects
None yet
Development

No branches or pull requests