17

I've started to create a series of interactive notebooks for a DSP lecture. So far, I've managed to copy & implement the MWE pasted below. However, in addition to the matplotlib figure containing the animation, I'm always getting an empty Matplotlib window. Any ideas how to suppress this behaviour?

python: 3.6.3 matplotlib: 2.0 and 2.1 IPython: 5.3.0 OS: Win 7 64 bit

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

from matplotlib import animation
from IPython.display import HTML

plt.rcParams['figure.figsize'] = (5,3)
plt.rcParams['figure.dpi'] = 100
plt.rcParams['savefig.dpi'] = 100
plt.rcParams["animation.html"] = "jshtml"  # for matplotlib 2.1 and above, uses JavaScript
#plt.rcParams["animation.html"] = "html5" # for matplotlib 2.0 and below, converts to x264 using ffmpeg video codec
t = np.linspace(0,2*np.pi)
x = np.sin(t)

fig, ax = plt.subplots()
ax.axis([0,2*np.pi,-1,1])
l, = ax.plot([],[])

def animate(i):
    l.set_data(t[:i], x[:i])

ani = animation.FuncAnimation(fig, animate, frames=len(t))
ani

The notebook can also be viewed under:

https://github.com/chipmuenk/dsp_fpga/blob/master/notebooks/01_LTI/MWE_animation.ipynb

In the static rendering at github, only the empty plot window shows, not the JavaScript animation.

3
  • Remove the magic %matplotlib inline or use %matplotlib agg instead. Commented Nov 6, 2017 at 14:15
  • I had tried different backends but the problem is that the notebooks will run on a virtual server which the students will log in to and interact with their browser. To me it seemed the cleanest solution to limit the output to one window. Commented Nov 6, 2017 at 14:34
  • Both workarounds render everything in the browser but without the empty figure. Commented Nov 6, 2017 at 14:45

3 Answers 3

18

This has nothing to do with an animation.

The lines

%matplotlib inline
import matplotlib.pyplot as plt
fig, ax = plt.subplots()

will create an output with an empty figure.

You may prevent the output of a cell in jupyter notebook using %%capture.

Cell1:

%%capture
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation
plt.rcParams["animation.html"] = "jshtml"
import numpy as np

t = np.linspace(0,2*np.pi)
x = np.sin(t)

fig, ax = plt.subplots()
h = ax.axis([0,2*np.pi,-1,1])
l, = ax.plot([],[])

def animate(i):
    l.set_data(t[:i], x[:i])

ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))

Cell2:

ani

enter image description here

Sign up to request clarification or add additional context in comments.

5 Comments

Neat! When surfing for %%capture I found another solution: fig, ax = plt.subplots() plt.close(); also did the trick for me. The handles to fig and ax obviously are not deleted by closing the plot. Are there reasons to prefer the one or the other solution?
No, the reason that both solutions work is actually the same: the plot is closed. Either by moving to the next cell or by closing it already within the cell. Choose whichever method you like better.
Just the control buttons!
This only plots the x values when I put this into a function
I found that using plt.close() after the line creating the animation (ani = ...) was important to keep my animation from being blank.
15

You can add plt.close() before the last line.

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

from matplotlib import animation
from IPython.display import HTML

plt.rcParams['figure.figsize'] = (5,3)
plt.rcParams['figure.dpi'] = 100
plt.rcParams['savefig.dpi'] = 100
plt.rcParams["animation.html"] = "jshtml"  # for matplotlib 2.1 and above, uses JavaScript
#plt.rcParams["animation.html"] = "html5" # for matplotlib 2.0 and below, converts to x264 using ffmpeg video codec
t = np.linspace(0,2*np.pi)
x = np.sin(t)

fig, ax = plt.subplots()
ax.axis([0,2*np.pi,-1,1])
l, = ax.plot([],[])

def animate(i):
    l.set_data(t[:i], x[:i])

ani = animation.FuncAnimation(fig, animate, frames=len(t))
plt.close()
ani

Comments

3

Here is an alternative example:

%matplotlib inline
from matplotlib import animation, pyplot as plt
import numpy as np
plt.rc('animation', html='html5')

data = np.random.random(20)
fig = plt.figure()

ax = fig.add_subplot(111)   
ax.plot(data) # draw background

anim = animation.ArtistAnimation(fig, [[ax.scatter(x, y)] for x, y in enumerate(data)])
anim

The result (anim) is shown animated, but the potential side-effect is an additional display of the static frame. This side-effect vanishes if the plt.figure call occurs in a separate cell before the add_subplot method.

This works because (like ImportanceOfBeingErnest said) the creation of a new figure causes the side effect of displaying a static image (depicting how the figure was left at the conclusion of the current cell evaluation in the notebook). But if nothing has been populated onto the figure yet (not even the axes), you prevent any image from being displayed (without needing jupyter magic to suppress it).

1 Comment

Another alternative is to omit %matplotlib inline entirely, or if that isn't feasible, then to repeat it immediately after the figure intended for animation is created. This resets the magic of displaying static figures which aren't otherwise part of the cell result; the animation itself is being displayed by a completely different mechanism (involving the html formatting of the cell evaluation result).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.