Suppress display of final frame in matplotlib animation in jupyter - python

I am working on a project that involves generating a matplotlib animation using pyplot.imshow for the frames. I am doing this in a jupyter notebook. I have managed to get it working, but there is one annoying bug (or feature?) left. After the animation is created, Jupyter shows the last frame of the animation in the output cell. I would like the output to include the animation, captured as html, but not this final frame. Here is a simple example:
import numpy as np
from matplotlib import animation
from IPython.display import HTML
grid = np.zeros((10,10),dtype=int)
fig1 = plt.figure(figsize=(8,8))
ax1 = fig1.add_subplot(1,1,1)
def animate(i):
grid[i,i]=1
ax1.imshow(grid)
return
ani = animation.FuncAnimation(fig1, animate,frames=10);
html = HTML(ani.to_jshtml())
display(html)
I can use the capture magic, but that suppresses everything. This would be OK, but my final goal is to make this public, via binder, and make it as simple as possible for students to use.
I have seen matplotlib animations on the web that don't seem to have this problems, but those used plot, rather than imshow, which might be an issue.
Any suggestions would be greatly appreciated.
Thanks,
David

That's the answer I got from the same thing I was looking for in 'jupyter lab'. Just add plt.close().
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
from IPython.display import HTML
grid = np.zeros((10,10),dtype=int)
fig1 = plt.figure(figsize=(8,8))
ax1 = fig1.add_subplot(1,1,1)
def animate(i):
grid[i,i]=1
ax1.imshow(grid)
return
ani = animation.FuncAnimation(fig1, animate,frames=10);
html = HTML(ani.to_jshtml())
display(html)
plt.close() # update

Related

How to save a matplotlib.pause animation to video?

I have an animation created with plt.pause as below...
import matplotlib.pyplot as plt
for i in range(10):
plt.scatter(0, i)
plt.pause(0.01)
plt.show()
How can I save this as a video file, e.g. a .mp4 file?
First, I have to redefine the plotting as a function with the plotted point given by a frame i. plt.pause() can be replaced by matplotlib.animate. Finally, I used a package suggested here to get the conversion to .mp4 format. You will need to install MoviePy:
pip install MoviePy
and then I just animate the function with matplotlib.animate into a .gif format before sending it to MoviePy. You'll need to figure out what directory you want this all to happen in. I'm just using the current working directory.
Here is the code:
import matplotlib.pyplot as plt
import matplotlib.animation as ani
import os
import moviepy.editor as mp
frames=20
fig = plt.figure()
ax = plt.gca()
def scatter_ani(i=int):
plt.scatter(0, i)
name = r"\test.gif"
path = str(os.getcwd())
anim = ani.FuncAnimation(fig, scatter_ani, frames = frames, interval=50)
anim.save(path+name)
clip = mp.VideoFileClip(path+name)
clip.write_videofile(path+r"\test.mp4")
The gif is then
To tweak the length of the animation, check out the docs for matplotlib.animate. For example, if you want to clear all of the previous data-points and show only the dot moving up, then you need to clear the axes in the function, and bound the y-axis so you see the motion ie
def scatter_ani(i=int):
ax.clear()
ax.set_ylim(0, frames+1)
plt.scatter(0, i)
to get:

Viewing Matplotlib funcAnimation live plots in browser

I am generating a live plot using matplotlib's funcAnimation function such as in the example below. To be clear I am plotting data that is dynamically updating in real-time and I want to view these updates in the browser rather than in its own local plotting window.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
import mpld3
def animate(i):
plt.clf()
#generate random data
x = np.array([i for i in range(100)])
y = np.random.normal(loc=0,scale=1, size = 100)
plt.scatter(x,y)
def main():
fig = plt.figure()
ani = animation.FuncAnimation(fig, animate, interval=1000)
ani.save('animation.gif', fps=10)
plt.show()
#mpld3.show()
if __name__ == '__main__':
main()
It opens the plot in its own little window.
I was wondering what is the best/quickest way to open this in browser instead? I tried using mpld3 as recommended in some places (see the commented bits of code in my code snippet), but all I get is a static page that does not update. I would like the plot to be redrawn in the browser during each redraw done by the animate fuction as it does when the plot is generated in it's own window instead as in the first image.
Thanks in advance for any help anyone has to offer!

Matplotlib FuncAnimation not plotting any chart inside Jupyter Notebook

Simple matplotlib plot. Here is my code
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
from itertools import count
import random
x = []
y = []
index=count()
def animate(i):
x.append(next(index))
y.append(random.randint(0,10))
plt.plot(x,y)
a = FuncAnimation(plt.gcf(),animate,interval=1000)
plt.tight_layout()
plt.show()
Running the code above I get
<Figure size 576x396 with 0 Axes>
but no chart appears.
Are you using Jupyter notebooks to run it? I tried with native libraries and it works just fine. The plots are visible.
Checking here i see the same situation. Could you try to use %matplotlib inline before importing matplotlib as:
%matplotlib inline # this line before importing matplotlib
from matplotlib import pyplot as plt
That said, the animation can be displayed using JavaScript. This is similar to the ani.to_html5() solution, except that it does not require any video codecs.
from IPython.display import HTML
HTML(a.to_jshtml())
this answer brings a more complete overview...

iPython notebook with Matplotlib only drawing the last fig.canvas.draw() call [duplicate]

I am trying to put animations in an iPython notebook and am not finding a solution. I saw one post that discussed using interactive widgets, but there are a couple problems that I have with this: First, every example I see with widgets uses a slider or some other input, whereas I just want the animation to run automatically when the cell is run. Second, all the documentation seems out of date on Jupyter's site--whenever I download and run their notebooks I get these messages about certain modules being deprecated and then later in the file something fails to run, presumably because they're trying to import and access files that no longer exist.
I've seen a few other pages on the topic but they often require downloading binaries or other modules, but I'm partly using this to teach some students Math and I've gotten them to download Anaconda--I was hoping to not further confuse the issue by making them also download and install more complicated things all while spending time not talking about the Math.
So in short, is there a way that I can create animations in an iPython notebook that only require the use of simple import commands that will run out-of-the-box so to speak with the software that comes from Anaconda?
[Edit: I should also note that I've used Tkinter to make animations, and I could make one in matplotlib I'm sure. So if there were a way to get the animations you produce with those to render in an iPython notebook, that would certainly be a working solution for me.]
[Further edit: I suppose I could also say what I am hoping to animate at the moment, although I really want to be pretty flexible about the range of things I could animate if I decide to. Right now I'm trying to make a digital clock that displays each digit in Sumerian base-60 numerals to illustrate a different counting and base system. So it should initially display | then after a second || and so on until ten gets represented as < and so on until eventually the clock ticks over to a minute where it now displays |:| to represent one minute, one second.]
[Note to future humans: If you're implementing some animation and are willing to publicly host it, please leave a link to it in the comments! I'm curious to see how people are making animations these days, and also a little curious to see what they're animating.]
Some options you have for animating plots in Jupyter/IPython, using matplotlib:
Using display in a loop Use IPython.display.display(fig) to display a figure in the output. Using a loop you would want to clear the output before a new figure is shown. Note that this technique gives in general not so smooth resluts. I would hence advice to use any of the below.
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
from IPython.display import display, clear_output
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
for i in range(len(x)):
animate(i)
clear_output(wait=True)
display(fig)
plt.show()
%matplotlib notebook Use IPython magic %matplotlib notebook to set the backend to the notebook backend. This will keep the figure alive instead of displaying a static png file and can hence also show animations.
Complete example:
%matplotlib notebook
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
plt.show()
%matplotlib tk Use IPython magic %matplotlib tk to set the backend to the tk backend. This will open the figure in a new plotting window, which is interactive and can thus also show animations.
Complete example:
%matplotlib tk
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
plt.show()
Convert animation to mp4 video (option mentionned by #Perfi already):
from IPython.display import HTML
HTML(ani.to_html5_video())
or use plt.rcParams["animation.html"] = "html5" at the beginning of the notebook.
This will require to have ffmpeg video codecs available to convert to HTML5 video. The video is then shown inline. This is therefore compatible with %matplotlib inline backend. Complete example:
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "html5"
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
ani
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
from IPython.display import HTML
HTML(ani.to_html5_video())
Convert animation to JavaScript:
from IPython.display import HTML
HTML(ani.to_jshtml())
or use plt.rcParams["animation.html"] = "jshtml" at the beginning of the notebook.
This will display the animation as HTML with JavaScript. This highly compatible with most new browsers and also with the %matplotlib inline backend. It is available in matplotlib 2.1 or higher.
Complete example:
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "jshtml"
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
ani
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
from IPython.display import HTML
HTML(ani.to_jshtml())
You may find this tutorial interesting.
If you can turn what you need into a matplotlib animation, and I'm fairly sure from your description that it's possible, you can then use
from matplotlib import rc, animation
rc('animation', html='html5')
and display your animation using
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=N, interval=20, blit=True)
anim
Might come in handy!
Jupyter widgets is a good way of displaying animations. The code below displays an animated gif.....
from ipywidgets import Image
from IPython import display
animatedGif = "animatedGifs/01-progress.gif" #path relative to your notebook
file = open(animatedGif , "rb")
image = file.read()
progress= Image(
value=image,
format='gif',
width=100,
height=100)
display.display(progress)
You can close this animation using:
progress.close()
N.B. I found a few nice animated gifs from http://www.downgraf.com/inspiration/25-beautiful-loading-bar-design-examples-gif-animated/.
I had a similar problem, and this question helped me get started. I put together a notebook that illustrates using FuncAnimation along with good explanations of why the notebook does some things the way it does. It also has links to instructions on FFmpeg. It also has links to the examples I used in developing and understanding of animations. You can view my contribution at:
Animation Illustration
For your question, you might find interactive sliders a better tool. I also created a notebook which demonstrates interactive widgets in Jupyter. It is available here; however, the interactive parts don't work there.
Both are available in a GitHub Repostory

Matplotlib animate - empty axis [duplicate]

I am trying to put animations in an iPython notebook and am not finding a solution. I saw one post that discussed using interactive widgets, but there are a couple problems that I have with this: First, every example I see with widgets uses a slider or some other input, whereas I just want the animation to run automatically when the cell is run. Second, all the documentation seems out of date on Jupyter's site--whenever I download and run their notebooks I get these messages about certain modules being deprecated and then later in the file something fails to run, presumably because they're trying to import and access files that no longer exist.
I've seen a few other pages on the topic but they often require downloading binaries or other modules, but I'm partly using this to teach some students Math and I've gotten them to download Anaconda--I was hoping to not further confuse the issue by making them also download and install more complicated things all while spending time not talking about the Math.
So in short, is there a way that I can create animations in an iPython notebook that only require the use of simple import commands that will run out-of-the-box so to speak with the software that comes from Anaconda?
[Edit: I should also note that I've used Tkinter to make animations, and I could make one in matplotlib I'm sure. So if there were a way to get the animations you produce with those to render in an iPython notebook, that would certainly be a working solution for me.]
[Further edit: I suppose I could also say what I am hoping to animate at the moment, although I really want to be pretty flexible about the range of things I could animate if I decide to. Right now I'm trying to make a digital clock that displays each digit in Sumerian base-60 numerals to illustrate a different counting and base system. So it should initially display | then after a second || and so on until ten gets represented as < and so on until eventually the clock ticks over to a minute where it now displays |:| to represent one minute, one second.]
[Note to future humans: If you're implementing some animation and are willing to publicly host it, please leave a link to it in the comments! I'm curious to see how people are making animations these days, and also a little curious to see what they're animating.]
Some options you have for animating plots in Jupyter/IPython, using matplotlib:
Using display in a loop Use IPython.display.display(fig) to display a figure in the output. Using a loop you would want to clear the output before a new figure is shown. Note that this technique gives in general not so smooth resluts. I would hence advice to use any of the below.
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
from IPython.display import display, clear_output
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
for i in range(len(x)):
animate(i)
clear_output(wait=True)
display(fig)
plt.show()
%matplotlib notebook Use IPython magic %matplotlib notebook to set the backend to the notebook backend. This will keep the figure alive instead of displaying a static png file and can hence also show animations.
Complete example:
%matplotlib notebook
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
plt.show()
%matplotlib tk Use IPython magic %matplotlib tk to set the backend to the tk backend. This will open the figure in a new plotting window, which is interactive and can thus also show animations.
Complete example:
%matplotlib tk
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
plt.show()
Convert animation to mp4 video (option mentionned by #Perfi already):
from IPython.display import HTML
HTML(ani.to_html5_video())
or use plt.rcParams["animation.html"] = "html5" at the beginning of the notebook.
This will require to have ffmpeg video codecs available to convert to HTML5 video. The video is then shown inline. This is therefore compatible with %matplotlib inline backend. Complete example:
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "html5"
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
ani
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
from IPython.display import HTML
HTML(ani.to_html5_video())
Convert animation to JavaScript:
from IPython.display import HTML
HTML(ani.to_jshtml())
or use plt.rcParams["animation.html"] = "jshtml" at the beginning of the notebook.
This will display the animation as HTML with JavaScript. This highly compatible with most new browsers and also with the %matplotlib inline backend. It is available in matplotlib 2.1 or higher.
Complete example:
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "jshtml"
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
ani
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
from IPython.display import HTML
HTML(ani.to_jshtml())
You may find this tutorial interesting.
If you can turn what you need into a matplotlib animation, and I'm fairly sure from your description that it's possible, you can then use
from matplotlib import rc, animation
rc('animation', html='html5')
and display your animation using
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=N, interval=20, blit=True)
anim
Might come in handy!
Jupyter widgets is a good way of displaying animations. The code below displays an animated gif.....
from ipywidgets import Image
from IPython import display
animatedGif = "animatedGifs/01-progress.gif" #path relative to your notebook
file = open(animatedGif , "rb")
image = file.read()
progress= Image(
value=image,
format='gif',
width=100,
height=100)
display.display(progress)
You can close this animation using:
progress.close()
N.B. I found a few nice animated gifs from http://www.downgraf.com/inspiration/25-beautiful-loading-bar-design-examples-gif-animated/.
I had a similar problem, and this question helped me get started. I put together a notebook that illustrates using FuncAnimation along with good explanations of why the notebook does some things the way it does. It also has links to instructions on FFmpeg. It also has links to the examples I used in developing and understanding of animations. You can view my contribution at:
Animation Illustration
For your question, you might find interactive sliders a better tool. I also created a notebook which demonstrates interactive widgets in Jupyter. It is available here; however, the interactive parts don't work there.
Both are available in a GitHub Repostory

Categories