microsoft / vscode-jupyter

VS Code Jupyter extension
https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter
MIT License
1.28k stars 290 forks source link

Plotly graph animations do not work in jupyter notebook #4364

Closed AnupamSaraph closed 2 years ago

AnupamSaraph commented 3 years ago

Environment data

Expected behaviour

plotly

See: https://plotly.com/python/animations/

Actual behaviour

Animation does not work in Visual Code with plotly.express but works in Google Collaboratory.

The output from VisualCode-jupyter is pasted below. In case of executing the code in Visual Code the graph does not animate and moving the slider has no effect on the graph.

plotlyinvisualcode

Steps to reproduce:

The code tested for plotting with animation is:

import plotly.express as px
df = px.data.gapminder()

fig = px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country",

       size="pop", color="continent", hover_name="country", facet_col="continent",
       log_x=True, size_max=45, range_x=[100,100000], range_y=[25,90])
fig.show()

rchiodo commented 3 years ago

Thanks for the bug. I believe plotly would be better able to look at this as it looks like something isn't working in plotly itself. If you open the 'Developer Webview Tools', it throws up a bunch of warnings:

image

Those warnings appear if you drag the slider.

rchiodo commented 3 years ago

@archmoj do you have any ideas about what might be happening?

archmoj commented 3 years ago

@archmoj do you have any ideas about what might be happening?

@nicolaskruchten could you please investigate?

AnupamSaraph commented 3 years ago

Thanks for the bug. I believe plotly would be better able to look at this as it looks like something isn't working in plotly itself. If you open the 'Developer Webview Tools', it throws up a bunch of warnings:

image

Those warnings appear if you drag the slider.

Thank you for your investigating the issue and taking it up. I have also raised the issue with your observations here: https://github.com/plotly/plotly.js/issues/5401#issue-785876448

AnupamSaraph commented 3 years ago

@archmoj do you have any ideas about what might be happening?

@nicolaskruchten could you please investigate?

@nicolaskruchten were you able to investigate?

nicolaskruchten commented 3 years ago

I won't get a chance to investigate this for a little while unfortunately. We need to figure out what's different about the VSCode Javascript context compared to on other pages or in vanilla Jupyter, where this JS code executes just fine.

nicolaskruchten commented 3 years ago

Related to https://github.com/microsoft/vscode-jupyter/issues/1589 I believe

lyyc199586 commented 3 years ago

Similar problem for html5 animation.

AnupamSaraph commented 3 years ago

It has been a while without any resolution in sight. I've had to move my project from vs-code. Is there any chance this will get resolved soon?

AnupamSaraph commented 3 years ago

@archmoj do you have any ideas about what might be happening?

@nicolaskruchten could you please investigate?

Do see: https://github.com/plotly/plotly.js/issues/5401#issuecomment-796956782

AnupamSaraph commented 3 years ago

Thanks for the bug. I believe plotly would be better able to look at this as it looks like something isn't working in plotly itself. If you open the 'Developer Webview Tools', it throws up a bunch of warnings:

image

Those warnings appear if you drag the slider.

This appears to be vs-code specific. Do see: https://github.com/plotly/plotly.js/issues/5401#issuecomment-796956782

jackthepanisher commented 3 years ago

This seems to be an issue with the 'plotly_mimetype' renderer that is used in VS Code per default ('vscode' is an alias of 'plotly_mimetype). There are two possible work-arounds depending what Plotly API is used.

If using plotly.express, the default renderer can be changed:

import plotly.io as pio
pio.renderers.default = 'notebook_connected'

This will change the renderer to a version that uses the Plotly JS code directly and in online mode.

If using plotly.graph_objects you can change the default renderer as above or call out the renderer explicitly during fig.show() calls:

fig.show(renderer='notebook_connected')

The renderer can also be changed to 'notebook' which is the offline version of 'notebook_connected' but it will increase the size of your notebook files. Both methods produce animated and interactive Plotly graphs as expected. Another side effect is that the graphs will also scale with the output cell now.

This method also applies to #4578. #1589 and maybe others.

greazer commented 3 years ago

Let's consider adding a statement to the Readme and/or FAQ for this.

dynamicwebpaige commented 3 years ago

Just to confirm - this issue has still not been resolved? I'm getting a blank canvas when attempting to replicate using the latest Insiders' Build edition of VS Code: Screen Shot 2021-04-21 at 1 01 52 PM

rchiodo commented 3 years ago

@jackthepanisher it looks like 'notebook_connected' renders nothing. Is there something else plotly needs to use the 'notebook' renderer?

nicolaskruchten commented 3 years ago

In general the idea in VSCode is to use the nteract renderer not the notebook one IIRC but I might be misremembering, and if the vscode renderer aliases to plotly_mimetype then I must be!

rchiodo commented 3 years ago

Yeah the nteract one has the same problem. :(

The notebook one is likely not working because the require call in the script won't work:

image

rchiodo commented 3 years ago

Yeah the console errors confirm that:

image

nicolaskruchten commented 3 years ago

From the Plotly side, I'd love to chat about a better/different way for VSCode Jupyter to support Plotly than the current system... a custom renderer on our end maybe? Something that would enable folks to use a version of Plotly.js of their own choosing rather than me PR'ing new JS into vscode-jupyter every so often :)

We'd need some help/guidance though... any interest in an exploratory call or something sometime?

rchiodo commented 3 years ago

@nicolaskruchten yes we'd love to collaborate. Let me chat with people internally on the when and how.

rchiodo commented 3 years ago

@DonJayamanne said you can e-mail him. His e-mail is part of his profile.

nicolaskruchten commented 3 years ago

Thanks! I just sent an email :)

jackthepanisher commented 3 years ago

@jackthepanisher it looks like 'notebook_connected' renders nothing. Is there something else plotly needs to use the 'notebook' renderer?

I'm not on an insider build but using VS Code 1.55.2 with plotly 4.14.3 and Python 3.9.4 everything is working fine with notebook/notebook_connected/iframe/iframe_connected for me. The plotly_mimetype/vscode only has issues with the interactive parts but seems to work ok otherwise. Again, I'm on release not on insider build so it might be different there. I also don't know enough details about plotly_mimetype and what benefits it would have over the other renderer types except the tighter control of the Plotly.js piece.

Edit: probably more useful to give the version of the Jupyter extension which is v2021.5.745244803

nicolaskruchten commented 3 years ago

FWIW, on a recently-updated version of VSCode/this plugin, I can get everything Plotly-related working (fig.show() and FigureWidget) with every interaction except for animations (i.e. panning, zooming, hovering, legend-clicking) without messing with the default renderer.

Using fig.show("notebook") and fig.show("notebook_connected") do result in animations working for me.

AnupamSaraph commented 3 years ago

FWIW, on a recently-updated version of VSCode/this plugin, I can get everything Plotly-related working (fig.show() and FigureWidget) with every interaction except for animations (i.e. panning, zooming, hovering, legend-clicking) without messing with the default renderer.

Using fig.show("notebook") and fig.show("notebook_connected") do result in animations working for me.

Code that works:

import plotly.express as px
import plotly.io as pio
#pio.renderers.default = 'notebook_connected'

df = px.data.gapminder()
fig = px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country",
           size="pop", color="continent", hover_name="country",
           log_x=True, size_max=55, range_x=[100,100000], range_y=[25,90])
fig.show('notebook')
jackthepanisher commented 3 years ago

If the notebook/iframe renderers work but the notebook_connected/iframe_connected renderers don't work it might be related to your internet connection/firewall setting/etc. The difference between the connected and the non-connected version is that the first will load the plotly.js JavaScript library from an online location while the latter will embed an offline version into the notebook output.

greazer commented 3 years ago

Putting in October due to number of users running into this.

rchiodo commented 2 years ago

Not sure what the work here is? The workaround/way to do things is to use code like so:

import plotly.express as px
import plotly.io as pio
#pio.renderers.default = 'notebook_connected'

df = px.data.gapminder()
fig = px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country",
           size="pop", color="continent", hover_name="country",
           log_x=True, size_max=55, range_x=[100,100000], range_y=[25,90])
fig.show('notebook')

Are we going to try and detect this? Push a change to plotly to detect VS code and always use the 'notebook' renderer?

des4cing commented 2 years ago

In my enviroment, this can be work: import plotly.io as pio pio.renderers.default = 'notebook'

but that does not work: pio.renderers.default = 'notebook_connected'

rchiodo commented 2 years ago

Still not sure what we want to do here. We can't fix this in our code. Plotly might detect VS code and switch to using the 'notebook' renderer by default.

What do we want to do with this issue?

greazer commented 2 years ago

I think the most appropriate change here is to modify plotly to discover it's running in vscode and change it's default. I believe this has been done for other notebook implementations (google colab, for instance).

rchiodo commented 2 years ago

PR for plotly is here: https://github.com/plotly/plotly.py/pull/3561

@nicolaskruchten, would you mind reviewing? Thanks.

nicolaskruchten commented 2 years ago

Yes, will review.

nicolaskruchten commented 2 years ago

I've commented in the PR... Sorry to be so out of the loop for a while there!

We can't fix this in our code

True, you can't force Plotly to use one renderer instead of another from VSCode's code, but my hope would be that we can figure out why animations specifically aren't working in VSCode using the current mime-type renderer, which works fine in JupyterLab. There's something about the way things are loaded right now that doesn't work, and I'd like to actually fix it instead of just switching up the way things work, if possible.

rchiodo commented 2 years ago

Fair enough. Thanks for the feedback. I'll close the PR and do some more investigation. Didn't realize using the 'notebook' renderer causes the entire library to end up in each cell.

The root cause it likely something not loading correctly when loading the plotly.js bits.

nicolaskruchten commented 2 years ago

I don't think it necessarily ends up in every cell, or at least that's not what happens in classic Jupyter Notebooks. There's some state tracking so that the bundle ends up loaded once per notebook, but still, it's a multi-meg bundle, so even that can be problematic. It's a tradeoff, though, because the advantage of this approach is that the version of the bundle always matches the version of Plotly.js that Plotly.py is built on. Under the current approach, the version of Plotly.js that's used is the one that's in the Jupyter Notebook Renderers extension, so this extension occasionally needs to be updated both by developers and then users. Neither side of this tradeoff is ideal :)

jackthepanisher commented 2 years ago

I second that trying to fix animations to work with the plotly_mimetype renderer in VS code is a better solution than switching renderers in the background. There should be a consistent renderer type that is getting used unless a user explicitly defines what renderer to use. There would also be issues with the scope of this kind of auto detection, would it apply to the whole notebook or just an individual cell? If it can't work with plotly_mimetype renderer in VS code, I would rather just have a warning output than some magic renderer switching in the background. The only exception might be if a user specifies something like renderer='vscode+notebook'.

rchiodo commented 2 years ago

I'm guessing this is part of the problem.

image

VS code doesn't implement all of requirejs, only parts of it.

rchiodo commented 2 years ago

Related: https://github.com/microsoft/vscode/issues/110503

EelcoLeo commented 2 years ago

I am new to github, python (version 3.9.7) and plotly. Try to follow some tutorials and I see that in VS studio (version 1.64.2) the animation or moving the slider does not work. (df = px.data.gapminder() tutorial as also shown in this topic) A lot of conversation is going on this topic since last year 13 jan 2021, but is there any resolution? I am newbee so explain in simple words please! Thanks in advance. Eelco email: eelcoleo.schiperus@gmail.com

rchiodo commented 2 years ago

@EelcoLeo the workaround is to do this:

import plotly.io as pio
pio.renderers.default = 'notebook'

That will force a copy of the renderer to load in every output and animations should work.

This issue is to figure out why the global renderer does not support animations. It has not been resolved yet.

EelcoLeo commented 2 years ago

Hi Rchiodo,

It is very strange now that I have a code with and without the suggested lines:

import plotly.io as pio pio.renderers.default = 'notebook'

and both graphs work.

First code with loading the renderer: afbeelding The animation works.

import plotly.express as px import plotly.io as pio import plotly.graph_objects as go pio.renderers.default = 'notebook_connected'

df = px.data.gapminder()

deze animatie werkt met facets of wel kolommen, zie facet_col="continent"

px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country", size="pop", color="continent", hover_name="country", facet_col="continent", log_x=True, size_max=45, range_x=(100,100000), range_y=(25,90))

A second program is also working but now without the suggested lines: afbeelding

import plotly.graph_objects as go '''' import plotly.io as pio pio.renderers.default = 'notebook' '''

px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country", size="pop", color="continent", hover_name="country", facet_col="continent", log_x=True, size_max=45, range_x=(100,100000), range_y=(25,90)) It is very confusing!! Is the software stable or what is happening. (Hope you can retrieve the png, otherwise let me know please)

Another question: I following a tutorial of geeks for geeks:

https://www.geeksforgeeks.org/covid-19-analysis-and-visualization-using-plotly-express/

At the point: Step 4: Bar graphs- Comparisons between COVID infected countries in terms of total cases, total deaths, total recovered & total tests

I copied the following code: (all modules are loaded and data is read in previous code) px.bar(dataset1.head(15), x = 'Country/Region', y = 'TotalCases',color = 'TotalCases', height = 500,hover_data = ['Country/Region', 'Continent'])

It does not work, no barchart is plotted. Any idea why?

Thanks very much sofar, hope you can help out.

rchiodo commented 2 years ago

Sorry I'm not a plotly expert. You'd be better off asking in plotly issues.

jackthepanisher commented 2 years ago

@EelcoLeo don't use the colab renderer in VS code. It is a custom renderer for use with Google Colab. Use vscode or notebook/notebook_connected depending on the need for the workaround for Plotly animations. Your first issue is probably related to setting a renderer using pio.renderers.default first and then commenting out that line of code. It will keep the setting from your last run so you will need to either restart the Python kernel or set it to the actual renderer that you want, vscode would be the default in VS Code.

EelcoLeo commented 2 years ago

thanks Jack: I used the following code:

import plotly.io as pio pio.renderers.default = "vscode"

That actually seems to work, graphs are somewhat awkward: afbeelding

Nevertheless I can now start to get some data of pension funds to check my pension fund performance compared to the others here in the Netherlands.

Thanks to all. Regards

dlangerm commented 2 years ago

Going to jump in here and add my two cents. Before, I was attempting to plot a violin plot with Plotly express, and it completely hung my editor requiring me to kill VScode. Once it did plot, I could no longer interact with anything in the notebook.

I then tried restarting VScode, but I work in dev containers, and there were all kinds of file handles and sockets left open by the renderer (at least, they looked like renderer processes, could have been something else). BTW I'm on Ubuntu 20.04, not WSL.

The open file handles and hung processes meant that VSCode couldn't remove the previous container as it was waiting for its processes/file handles to close (it just hung at the docker container rm step). I ended up having to forcibly destroy and rebuild the container from the command line (not a huge deal tbh, but it was frustrating).

Suffice to say it was not a fantastic experience and I'll happily hand over all relevant logs and such to help make sure nobody else has to deal with that.

import plotly.io as pio
pio.renderers.default = "vscode"

This snippet fixed the problem, and while it's not the speediest thing in the world (it takes about 10-20 seconds or so for a new cell to run after plotting something), I can now plot inside of the vscode jupyter environment and (eventually) move onto the next cell.

jackthepanisher commented 2 years ago

@dlangerm, your problem doesn't seem to be related to Plotly animations not working correctly with the vscode renderer. I suggest to create another issue if you think your problem is connected to the vscode/jupyter extension. One thing I can suggest is to check what default renderer is used on your setup before setting it specifically. So with a fresh kernel restart do a print(pio.renderers.default) immediately after importing plotly.io.

rchiodo commented 2 years ago

I finally did some more investigation here (after updating our renderer to the latest plotly). The data coming back is not in a format that the renderer understands.

This line here fails: https://github.com/plotly/plotly.js/blob/68a4917e8967bb021929e819453ee84650f7bf6f/src/plot_api/plot_api.js#L64

Which means the frame list is never populated (and why the animation fails).

Data is not an object but rather an array. With plotly version 5.8.0, it generates data like so:

      "application/vnd.plotly.v1+json": {
       "config": {
        "plotlyServerURL": "https://plot.ly"
       },
       "data": [
        {
         "hovertemplate": "<b>%{hovertext}</b><br><br>continent=Asia<br>year=1952<br>gdpPercap=%{x}<br>lifeExp=%{y}<br>pop=%{marker.size}<extra></extra>",
         "hovertext": [
          "Afghanistan",
          "Bahrain",
          "Bangladesh",
...
},
...
],
"frames": [
        {
         "data": [
...

So it looks to me like the data returned from the python code is not expected by the JS code.

@nicolaskruchten does this sound feasible?

rchiodo commented 2 years ago

Oh looking further, nteract is the one parsing this data. I believe if I change nteract to pass the object one level up it might work. We might be able to fix this from our side (or submit a fix to nteract)

rchiodo commented 2 years ago

Yes that fixes it. I should be able to submit a temporary workaround to our postinstall. I'll create an issue in nteract and submit a fix there too.