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

Images not saved in *.ipynb #16

Closed
jklymak opened this issue Aug 14, 2017 · 53 comments · Fixed by #343
Closed

Images not saved in *.ipynb #16

jklymak opened this issue Aug 14, 2017 · 53 comments · Fixed by #343
Milestone

Comments

@jklymak
Copy link
Member

jklymak commented Aug 14, 2017

Maybe its a design decision, but if I use %matplotlib ipympl in a notebook, there is no image of plots I've made is saved in the *.ipynb file as there was for nbagg. Thats a huge usability issue for me.

I think the cool thing about notebooks is being able to see the output of your work without having to re-run all the code, some of which may no longer work (data moved etc), so this is a pretty big reversion in functionality for me. It also kills the ability to quickly post onto GitHub or gist, and even save as html no longer has a plot. If this is to replace nbagg I hope the image saving gets added back in.

Of course, maybe I'm just doing something incorrectly. This was with master on matplotlib and master on ipympl. Jupyter-notebook = 5.0.0

@SylvainCorlay
Copy link
Member

As of ipywidgets 7.0, widgets become regular output, and the live version will just be an item in the mime bundle.

With the matplotlib widget, we can certainly add an image in the mime bundle for the figure.

At jupytercon next week, we plan on doing some iterations on ipympl.

@tacaswell tacaswell modified the milestone: 0.1 Aug 26, 2017
@blink1073 blink1073 modified the milestones: 0.1, 0.2 Nov 20, 2017
@fperez
Copy link
Member

fperez commented Dec 11, 2017

Just to add I think this is a key usability feature to match the "old" nbagg/notebook backend. Being able to reload an old notebook or see it on a plain html render with a static png is really important. In nbagg, the seamlessness of how it saved the last static render on figure/notebook close was wonderful.

@gregerspoulsen
Copy link

@fperez : I agree - notebook is an excellent way to document your work, but to use it as such it must be possible to quickly load the notebook and figures without re-running a possibly time consuming analysis.

@tylerlekang
Copy link

Hi, I recently made the conversion from %matplotlib notebook to import ipympl, and have it working well ... but am sad to find out there is currently no way to “embed” a static version of whatever figures are in the notebook, for quick and easy viewing on GitHub.

A button with a caption like “embed current figure view as inline PNG” or something to that effect I think is plenty descriptive for users.

Thank you!

@tylerlekang
Copy link

Hi, just wondering if this has any chance to be updated soonish? It is a pain point not to be able to quickly view the resulting plots from a notebook's full run (which takes several hours...) on GitHub.

Is there any workaround? Even taking a screenshot, saving as .png, and being able to use some code to embed that? The plotting "widget" works great ... just have lost this really key feature ...

@blink1073
Copy link
Member

Hi @tylerlekang, I plan to implement this feature next week at the Jupyter Widget author workshop.

@tylerlekang
Copy link

Hi @blink1073 ,
Sorry to be a pest, but I do see new versions of matplotlib uploaded to pypi on Jan 21 and ipywidgets & widgetsnbextension uploaded onJan 24 ... but no new version of ipympl since Nov.

I did upgrade to the new versions of previously mentioned, but still no embedding of static image of plot figures saved in the notebook.

Would definitely appreciate it! Thank you sir! :)

@blink1073
Copy link
Member

@tylerlekang, I got caught up working on JupyterLab itself during the workshop and did not get a chance to work on this.

@tylerlekang
Copy link

Thank you for the update. Any workaround until the new feature available?

@jklymak
Copy link
Member Author

jklymak commented Jan 29, 2018

Doesn't %matplotlib notebook work, or do you need something specific from the new backend?

@tylerlekang
Copy link

I used %matplotlib notebook with Python 2.7 forever, and it worked great. But then I decided to upgrade everything to Python 3.6, which is what I'm sticking with going forward. After that upgrade, %matplotlib notebook stopped working so well (it was glitchy). I found a GitHub issues thread (think it was for Notebook) that sounded a lot like my issue, and in there they were saying that they wanted to start pushing users to ipympl. So I made that switch, and it works great .... just can't embed a static .png of the figure view into the notebook anymore for quick recall/viewing on GitHub (or when you first load a notebook).

@jklymak
Copy link
Member Author

jklymak commented Jan 29, 2018

I'm not switching until ipympl has this feature; I'm not sure what the point of a Notebook is without this feature. But I don't really have any problems with the old notebook backend.

@blink1073
Copy link
Member

@jasongrout, I looked into what it would take to do this, and then realized the issue is actually more general. I think what we really need is for an entire top level widget to be able to persist an image of itself, because a single widget may not be the entire output.

@tylerlekang
Copy link

tylerlekang commented Jan 29, 2018

Given this comment:

_As of ipywidgets 7.0, widgets become regular output, and the live version will just be an item in the mime bundle.

With the matplotlib widget, we can certainly add an image in the mime bundle for the figure._

can't the first attempt/implementation just be a static image of the figure view was when the notebook is saved/closed/etc?

That, as opposed to the idea of embedding or capturing the entire, fully interactive functionality of the plot figure (which would be cool, don't get me wrong).

@blink1073
Copy link
Member

What I mean is that a widget can be contained in a larger widget layout, so saving the an image of just the matplotlib widget would not be appropriate in that context.

@jasongrout
Copy link
Contributor

Good point. However, in general, it may be hard to "screenshot" various widgets correctly. I think the best we could do is build an api for asking for an HTML representation of a widget, which is then called recursively from the top-level widget, with perhaps the default giving a div with the width and height of the actual widget.

Perhaps for now, you can see if the matplotlib widget is the top-level widget and do your saving if it is. That might be enough to handle the 80-90% usecase for now. I think it might be a hack right now to see if you are at the top level (we make it easier in the classic notebook by setting a parent attribute on widgets, but something like that isn't in jlab right now).

@tylerlekang
Copy link

For what it's worth: I'm pretty certain ipympl is the only widget I'm using (in the classic notebook). The rest is just various python code in cells. So for that usecase at least, it would be very appreciated!

@tylerlekang
Copy link

tylerlekang commented Feb 6, 2018

Until and unless this is resolved, I have reverted to using the very simple %matplotlib inline method to get plots to embed in the saved notebook. I simply have to have it.

And as mentioned before, the %matplotlib notebook method stopped working for me once I switched to python 3.6. I tried it again and the same glitches/problems are still there.

@blink1073
Copy link
Member

@jasongrout, I should have also mentioned above that there is no API for a widget to add mime data. For the classic notebook we had hacked our way up to the parent cell and manually added an output.

@felixpatzelt
Copy link

Hey, are there any updates on this issue? I just switched to Jupyter lab and this is one of the biggest annoyances for me so far.

@SylvainCorlay
Copy link
Member

We spent some time with @danallan working on this during the sprints at scipy on saturday.

We have the main pieces together, a hack to make it work without any change in other projects and a longer-term solution requiring some changes in nbconvert and ipywidgets.

Stay tuned.

@hadim
Copy link

hadim commented Aug 3, 2018

Very nice to hear. This feature will make me totally switch to ipympl.

@fherwig
Copy link

fherwig commented Nov 19, 2018

We spent some time with @danallan working on this during the sprints at scipy on saturday.

We have the main pieces together, a hack to make it work without any change in other projects and a longer-term solution requiring some changes in nbconvert and ipywidgets.

Stay tuned.

Just wanted to add my great appreciation if this gets resolved!!!

@fperez
Copy link
Member

fperez commented Dec 22, 2018

@SylvainCorlay do you have any updates on this one? In practice this makes %matplotlib widget in JLab a pretty serious usability regression over %matplotlib notebook in classic...

I actually think it's somewhat connected to #4 - the closing behavior is also different and I wonder if both could be fixed in one shot...

Basically would the following logic be viable?

  • Upon comm close, widget output is removed from the page and figure is closed (in mpl).
  • Png output is produced and put in the mimebundle, so that upon removal of JS output, png one stays.

@SylvainCorlay
Copy link
Member

Hey @fperez

  • we were successful at adding a PNG representation to the mime bundle for Matplotlib figures, but the issue with this is that the widget view being in the mime bundle as well, it has a precedence over the image with the HTML exporter of nbconvert. So the image is not in the HTML.

  • To me, the solution is to get nbconvert to support keeping both PNG and widget repr in the HTML output, and have the embedded widget renderer replace the image preview. This would also apply to other widgets that can compute a PNG preview of themselves. This would be a significant change in nbconvert's templating mechanism.

Ideally, I would like to remove the hacks and special-casing for Matplotlib in Jupyter / IPython (and reversely) and only rely on the rich display mechanism. Just a _repr_mime_bundle_ on matplotlib object.

@martinRenou
Copy link
Member

Actually, saving the image data in the Widget state is of no help if the Widget state itself is not saved in the Notebook, which is not done automatically in the classic Jupyter Notebook (see jupyter-widgets/ipywidgets#1632).

I'll investigate a bit more tomorrow, see if we can find a hack around this for now. But in the long shot, it might be a good idea to open a PR in ipywidgets for automatically saving the widget state in the case of Jupyter Notebook.

@SylvainCorlay
Copy link
Member

@martinRenou this is some more context to this.

  1. There was demand for including a raw image mime type in the mime bundle.
  2. The issue is that even if such a raw image is available, but the js rendering the widgets is not present, the widget mime type has higher precedence than the image.

This may be solved with the "stop" button that you are adding which will completely remove the widget.

@jasongrout
Copy link
Contributor

2. The issue is that even if such a raw image is available, but the js rendering the widgets is not present, the widget mime type has higher precedence than the image.

Then presumably the right thing to do there is for the widget renderer to render the fallback image and/or text. This may require some work in (at least) JupyterLab to have a renderer call the rendering system to render a fallback.

@martinRenou
Copy link
Member

martinRenou commented Feb 27, 2020

Wouldn't it be simpler to have the image data as part of the Widget model, and to change a bit ipywidgets behavior so that the Widget state is always saved in the Notebook?

This means that there would be no action required from the user (no click on a button). And it would not require changing Jupyter Notebook nor JupyterLab (JupyterLab already supports automatically saving the Widget state).

@jasongrout
Copy link
Contributor

ipywidgets behavior so that the Widget state is always saved in the Notebook?

We used to do that (ipywidgets 4 maybe?), and the result was that almost all notebooks in practice became huge and bloated. If the primary usecase of interactive widgets was actual interaction with a kernel, they needed to be created fresh each run anyway, so it seemed very wasteful to save huge amounts of data by default (think an entire dataset for ipyvolume, for example). The compromise was to make it possible to save data, but not turn it on by default.

@martinRenou
Copy link
Member

I understand, it is indeed annoying.

But I guess using a checkbox like proposed in jupyter-widgets/ipywidgets#1632 would be the right way to go? This way you can always turn it off, but it does not require to click on "Save widget state" every single run.

@jasongrout
Copy link
Contributor

But I guess using a checkbox like proposed in jupyter-widgets/ipywidgets#1632 would be the right way to go?

Yes, as that discussion elaborates, having a checkbox is a much cleaner UX than the current classic notebook widgets menu. That's why we architected JupyterLab to enable such a checkbox.

@martinRenou
Copy link
Member

Would you be fine if I try opening a PR in the widgetsnbextension (I guess this would be the right place?) changing the "Save widgets state" button into a checkbox?

@jasongrout
Copy link
Contributor

think an entire dataset for ipyvolume, for example

Another usecase I can see coming up a lot is the new file upload widget - people upload a file, then save their notebook, and wonder why the entire contents of the file is saved in base64 with the notebook. That could introduce security issues as well - I bet most people wouldn't realize that saving widget state includes the entire contents of that uploaded file.

@jasongrout
Copy link
Contributor

Would you be fine if I try opening a PR in the widgetsnbextension (I guess this would be the right place?) changing the "Save widgets state" button into a checkbox?

Sure! I delved into a bit a long time ago (I think I mentioned this on the other thread), and came away with the conclusion that it was a deeper dive into the classic notebook javascript to enable a save hook than I wanted to do at the time.

@jasongrout
Copy link
Contributor

See jupyter-widgets/ipywidgets#2012 for my previous attempt.

@martinRenou
Copy link
Member

Thanks! I will look into it.

That could introduce security issues as well - I bet most people wouldn't realize that saving widget state includes the entire contents of that uploaded file.

So maybe the checkbox should not be checked by default... I guess this is the choice you've made in JupyterLab?
And maybe we should put a warning in the ipywidgets documentation concerning the FileUpload widget, saying that it might save the file content on the server.

@jasongrout
Copy link
Contributor

So maybe the checkbox should not be checked by default... I guess this is the choice you've made in JupyterLab?

Yes, that is the choice in JupyterLab - no saving by default.

And maybe we should put a warning in the ipywidgets documentation concerning the FileUpload widget, saying that it might save the file content on the server.

Great idea - it might save uploaded file content in the notebook if widget state is saved.

@martinRenou
Copy link
Member

What would be the the way to save this checkbox state from one Notebook session to the other? Is there a kind-of cookie saved by the widgetsnbextension where I can save its state?

@BrenBarn
Copy link

BrenBarn commented Apr 4, 2020

What is the status of this? It appears to be a major regression from %matplotlib notebook. If plots aren't saved in the notebook, it can't be effectively shared, making it nearly useless. Shouldn't this be a top priority?

@pyfrid
Copy link

pyfrid commented May 11, 2020

I think stop button #176 is already enough as a first step. It would be nice to have it as soon as possible. It is easier to press stop buttons in all figures in a notebook and convert it to html rather than making a screenshot for every plot manually.

@georgeholt1
Copy link

Is there any update to this issue? This majorly undermines the usability of Lab in many cases.

@martinRenou
Copy link
Member

Trying another approach in #294, as discussed in #150

@nvaytet
Copy link

nvaytet commented Aug 16, 2021

Just following up to ask if there is an update on this.
Being able to view figures in a notebook that was saved, without re-running the notebook is being requested by many users of our library.
Thanks!

@martinRenou
Copy link
Member

This is fixed in #343

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

Successfully merging a pull request may close this issue.