Is there a way to save the output of a cell?

Basically I want to make a plot from a cell, “save” the plot, tweak some code within the cell, remake the plot, and compare the two versions, all from within Jupyterlab. Is this possible? Or perhaps with an extension?

“Create New View From Output” is almost exactly what I want, except that the new view always updates to the most recent output of that cell. I really just want a snapshot of the output. Otherwise the behavior where the output becomes a new tab which I can place wherever I want is perfect.

Any suggestions? Thanks.

Maybe this project will help you accomplish this:

It seems pretty cool!

2 Likes

That is super cool, I did not know about it! It basically works, even with Julia (which wasn’t clear from the docs if its Python only), and I’m able to simultaneously view old versions of a plot like I needed. One downside is that I can’t put each version into its own tab to conveniently flip between them, plus its definiely got some rough edges being alpha, but overall I’m pretty impressed!

1 Like

If you are using IPython, you could try the %%capture magic to get the plot data:

https://ipython.readthedocs.io/en/stable/interactive/magics.html#cellmagic-capture

oh and this project out of nteract is also pretty nifty, and might do what you like: https://github.com/nteract/scrapbook (I believe @MSeal may be working on this?)

1 Like

I need to check out @choldgraf’s awesome suggestions more because I think I could find uses for both of those. However, if you are looking for somethings more hacky I can offer these suggestions…

When you say ‘compare’ you mean visually just look at the plots yourself? Can you duplicate the notebook, make your changes, and then place it side-by-side next to the original? You can launch the duplicate in the same kernel if that helps save time. To attach the new notebook to the old kernel, you click on the kernel indicator in the upper right side of JupyterLab and select the kernel from the other notebook session.

Alternatively, add saving the plot as an image, if you can. (Otherwise you can most likely use %%capture magic, as suggested, and substitute in show() the way I use display image with the image handling suggestions that follow.) With the image you can do all sorts of things with IPython’s display ability. I have made notebooks that display a lot of images and then just use the new view ability in JupyterLab to place them side-by-side at different points for review. And you can add in html to tag different ones. Or you can see from a notebook in this repo where I automate switching between viewing different output to facilitate scanning for an image that looks striking among a lot of combinations. You can see it illustrated in a sped up manner in that gif that plays. The bottom two cells in the notebook here might give you some ideas to get closer to what you need. To get to the specific notebook actively, launch the binder and then click on ’ Demo of Sampling Various Combinations of Applying A Color Palette to a Complex’ in the list and run the notebook that comes up. If you do run the notebook to better get a sense what I am trying to describe, I’d suggest changing the fourth code cell to shuffles_to_do = 5 and the line that starts cmd.png in the fifth cell to cmd.png("img_{}.png".format(x), width=50, height=50, dpi=10, ray=0, quiet=0) so you don’t need to wait forever for fancy images you don’t care about.

It sounds somewhat like you want to clone the notebook and rerun with different parameters, or perhaps have two cells you wish to compare? The scrapbook project lets you save the results (plot or primitive data) and recall it programmatically, so if you were versioning your notebooks with different saves you could do:

sb.glue("my-plot", plot_obj, display=True)

in the notebook, then in a downstream notebook:

nb = sb.read_notebook('prior_notebook.ipynb')
nb.scraps["my-plot"]

Or if you wanted to re-render the scrap to compare visually:

nb = sb.read_notebook('prior_notebook.ipynb')
nb.reglue("my-plot")

The project hasn’t had recent updates, but that was somewhat intentional as I was working on other jupyter repos. I’m going to be actively contributing some more features now that some of my other open source tasks are done.

2 Likes

Thanks in advance - this project looks very promising!
Just a follow up - I’ve been trying to sb.glue a dataframe and also a df.plot()

sb.glue(“non_json”, df, ‘arrow’)
running into the following error
ScrapbookMissingEncoder: no encoder found for “none” data type:

Trying to glue a plot - df.plot(kind=‘bar’,x=‘names’,y=‘ages’) - which displays well in the notebook)
sb.glue(‘food_plot’,food_plot, display=True)

ScrapbookDataException: Scrap (name=food_plot) contents do not conform to required type structures: <matplotlib.axes._subplots.AxesSubplot object at 0x7f4142d81a00> is not of type ‘object’, ‘array’, ‘boolean’, ‘string’, ‘number’, ‘integer’

Failed validating ‘type’ in schema[‘properties’][‘data’]:
{’$id’: ‘#/properties/data’,
‘description’: 'The raw data in JSON format associated with this ’
‘Scrap’,
‘examples’: [‘data’],
‘title’: ‘scrap data’,
‘type’: [‘object’, ‘array’, ‘boolean’, ‘string’, ‘number’, ‘integer’]}

On instance[‘data’]:
<matplotlib.axes._subplots.AxesSubplot object at 0x7f4142d81a00>

Yeah the sb.glue(“non_json”, df, ‘arrow’) is a pending feature to support dataframes directly. I’ll be trying to get that added and released by the end of the month. Until then you have to convert the dataframe to json and back.

For the second error, try setting encoder = "display" as well to avoid it trying to save the plot object as a data field in addition to the display field.

1 Like