Skip to content

Instantly share code, notes, and snippets.

@ClementC
Created October 16, 2018 14:19
Show Gist options
  • Save ClementC/8cf6edf9eeccf1ab692db8f7dd8f2062 to your computer and use it in GitHub Desktop.
Save ClementC/8cf6edf9eeccf1ab692db8f7dd8f2062 to your computer and use it in GitHub Desktop.
Small script and descriptions of steps to extract a GIF for a matplotlib animation widget embedded in a Jupyter notebook.
# Matplotlib animations can be saved as a widget in a Jupyter notebook.
# It's unclear to how to recover it in Python once the notebook kernel has been restarted.
# But the image data is there in the notebook, embedded in a JS script in the output of the cell
# with the individual frames encoded as base64 png images.
# So here's the way I found to extract the images and make a GIF out of them.
# It's not all automatic and needs some manual action.
# Steps:
# 1/ Open the notebook in a web browser. Open the developer tools, and in the console, start typing "anim"
# then TAB to autocomplete. A variable with a unique name looking like "animae693007f74d44b0b917c61003e9490f" should appear.
# Cut this variable name, and copy it in the following command that you can then execute:
# JSON.stringify(animae693007f74d44b0b917c61003e9490f.frames.map(function(elem) {return elem.src;}))
# Copy the output that appears.
# 2/ Open your favorite text editor, preferably not terminal-based; the output can be several Mo of text,
# and terminal usually don't react well to this. I used Sublime Text for this step.
# Paste the output, and save it under "frames.json"
# 3/ Create a "frames" directory next to it
# 3/ Fire an IPython terminal, pip install imageio if you don't have it, and execute the code below.
# 4/ You can now admire the created GIF and marvel at the wonders of technology.
import base64
import json
import imageio
with open("frames.json") as f:
frames = json.load(f)
print("Found %d frames." % len(frames))
# Exporting individual frames as PNG images
for idx, frame in enumerate(frames):
with open("%d.png" % (idx + 1), "wb") as f:
f.write(base64.b64decode(frame.split("base64,")[1]))
# Opening all frames and creating a GIF
# With the options there it will loop, and each frame will be displayed for 200ms
with imageio.get_writer('./my_gif.gif', mode='I', duration=0.2) as writer:
filenames = ["./frames/%d.png" % i for i in range(1, 31)]
# If you want to have the GIF looping back-and-forth, you can replace the for-loop below by the commented one
# for filename in filenames + filenames[:-1:-1]:
for filename in filenames:
image = imageio.imread(filename)
writer.append_data(image)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment