How do I get rid of the static graph from matplotlib.animation? - python

Here's the code that produces an animation using matplotlib. When I run it in Jupyter notebook, I also get another static graph below the animated graph. How do I remove it?
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
fig, ax = plt.subplots()
x = np.arange(0, 20, 0.1)
ax.scatter(x, x + np.random.normal(0, 3.0, len(x)))
line, = ax.plot(x, x - 5, 'r-', linewidth=2)
def update(i):
label = 'timestep {0}'.format(i)
line.set_ydata(x - 5 + i)
ax.set_xlabel(label)
return line, ax
anim = FuncAnimation(fig, update, frames=np.arange(0, 10), interval=200)
HTML(anim.to_html5_video())

I use a module called JSAnimation (see this example notebook from the Author).
To display the animation, you simply call:
from JSAnimation.IPython_display import display_animation
display_animation(anim)

Related

Matplotlib Animation Blurry When Output From Jupyter Notebook

When I create an animated graph using matplotlib's FuncAnimation, the axis ticks and labels are blurry when I use Jupyter Notebook, as in this screenshot. This is not the case when I use Python from the console.
Here is a minimal working example that has this problem when I run it from a Jupyter notebook:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
x = np.linspace(0, 4*np.pi, 100)
y = np.sin(x)
fig, ax = plt.subplots()
the_plot, = ax.plot([], []) # Empty array for initialisation
ax.set_xlim(np.min(x), np.max(x))
ax.set_ylim(np.min(y), np.max(y))
def update(i):
the_plot.set_data(x[:i+1], y[:i+1])
anim = animation.FuncAnimation(fig, update, range(len(x)), save_count=len(x))
anim.save('Out.mp4', fps=25, writer='ffmpeg')

Showing subplots at each pass of a loop

I would essentially like to do the following:
import matplotlib.pyplot as plt
import numpy as np
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
for i in range(10):
ax1.scatter(i, np.sqrt(i))
ax1.show() # something equivalent to this
ax2.scatter(i, i**2)
That is, each time a point is plotted on ax1, it is shown - ax2 being shown once.
You cannot show an axes alone. An axes is always part of a figure. For animations you would want to use an interactive backend. Then the code in a jupyter notebook could look like
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
frames = 10
x = np.arange(frames)
line1, = ax1.plot([],[], ls="", marker="o")
line2, = ax2.plot(x, x**2, ls="", marker="o")
ax2.set_visible(False)
def animate(i):
line1.set_data(x[:i], np.sqrt(x[:i]))
ax1.set_title(f"{i}")
ax1.relim()
ax1.autoscale_view()
if i==frames-1:
ax2.set_visible(True)
fig2.canvas.draw_idle()
ani = FuncAnimation(fig1, animate, frames=frames, repeat=False)
plt.show()
If you want to change plots dynamically I'd suggest you don't redraw the whole plot every time, this will result in very laggy behavior. Instead you could use Blit to do this. I used it in a previous project. Maybe it can help you too if you just take the parts from this you need:
Python project dynamically updating plot

How to make jupyter HTML-matplotlib animation with seaborn heatmap?

I trying to make HTML(anim.to_html5_video) animation work in jupyter with seaborn heatmap.
First, I get working working samples from documentation, and make "pure matplotlib" image map animated example, it worked, with small problem ("parasite output" in animation cell)
Then, I tried to make it work with seaborn.heatmap… but failed. Animation looks like "infinite mirror" — obviously something wrong with matplotlib axes/plot composition, but I can't get it.
Common initialization cell:
import pandas as pd
import seaborn as sns
import numpy as np
%matplotlib inline
#%matplotlib notebook # Tried both, not needed for animation.
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from IPython.display import HTML
Animation worked, but "unwanted static output image exists":
fig, ax = plt.subplots()
nx = 50
ny = 50
line2d, = ax.plot([], [], lw=2)
def init():
line2d.set_data([], [])
ax.imshow(np.zeros((nx, ny)))
return (line2d,)
def animate(i):
data = np.random.rand(nx, ny)
ax.set_title('i: ' + str(i))
ax.imshow(data)
return (line2d,)
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=10, interval=1000, blit=False)
HTML(anim.to_html5_video())
So, looks that all OK with my jupyter setup (packages, ffmpeg, etc).
But, I cannot get how to make it with seaborn.heatmap:
fig, ax = plt.subplots()
nx = 50
ny = 50
line2d, = ax.plot([], [], lw=2)
ax_global = ax
def init_heatmap():
line2d.set_data([], [])
sns.heatmap(np.zeros((nx, ny)), ax=ax_global)
return (line2d,)
def animate_heatmap(i):
data = np.random.rand(nx, ny)
sns.heatmap(data, ax=ax_global)
ax.set_title('Frame: ' + str(i))
return (line2d,)
anim = animation.FuncAnimation(fig, animate_heatmap, init_func=init_heatmap,
frames=10, interval=1000, blit=True)
HTML(anim.to_html5_video())
Both samples ready to test on github
Of course, I want to see animation with random map and "stable heat-axes"
but get this
https://vimeo.com/298786185/
You can toggle the "colorbar". From the Seaborn.heatmap documentation, you need to change sns.heatmap(data, ax=ax_global) to sns.heatmap(data, ax=ax_global, cbar=False) and also do the same inside the init_heatmap().

Plot very small values with matplotlib in jupyter

I am trying to plot some extremely small values with matplotlib in jupyter notebook (on a macbook pro). However, regardless if I set the y-axis limits, all I get is a flat line. What I am after is something like the example (png) below with regard to y-axis notation. I also tried the same example outside of jupyter and I still get the same results. Here's the code suggested by Andrew Walker on my previous question:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(13,6))
ax = fig.add_subplot(111)
plt.hold(True)
xs = np.linspace(0, 1, 101)
ys = 1e-300 * np.exp(-(xs-0.5)**2/0.01)
ax.plot(xs, ys, marker='.')
Here's what I get:
And here's what I'm after:
The easiest thing to do is to just plot your values multiplied by 10^300, and then change the y-axis label:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(13,6))
ax = fig.add_subplot(111)
plt.hold(True)
xs = np.linspace(0, 1, 101)
ys = np.exp(-(xs-0.5)**2/0.01)
ax.plot(xs, ys, marker='.')
ax.set_ylabel(r'Value [x 10^{-300}]')
You can use the set_ylim method on your axes object to do what you need, simply change your code to this and it would do what you need:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(13,6))
ax = fig.add_subplot(111)
plt.hold(True)
xs = np.linspace(0, 1, 101)
ys = 1e-300 * np.exp(-(xs-0.5)**2/0.01)
ax.set_ylim([0,10^-299])
ax.plot(xs, ys, marker='.')
you may like to check This link for more info on this subject.

ipywidgets StaticInteract plots all images combination

I am using iPython notebook to test interactive functionalities. The following example (from here) worked fine for me several months ago. However, if I run it now, it plots all the images from possible combinations. I am not sure if this is a duplicate, but this didn't help.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
# mpl.rcParams['figure.max_open_warning'] = 1
def plot(amplitude, color):
fig, ax = plt.subplots(figsize=(4, 3),
subplot_kw={'axisbg':'#EEEEEE',
'axisbelow':True})
ax.grid(color='w', linewidth=2, linestyle='solid')
x = np.linspace(0, 10, 1000)
ax.plot(x, amplitude * np.sin(x), color=color,
lw=5, alpha=0.4)
ax.set_xlim(0, 10)
ax.set_ylim(-1.1, 1.1)
return fig
from ipywidgets import StaticInteract, RangeWidget, RadioWidget
StaticInteract(plot,
amplitude=RangeWidget(0.1, 1.0, 0.1),
color=RadioWidget(['blue', 'green', 'red']))
This is the output:
Can you help me?
This is how you can approach it.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from ipywidgets import interact, FloatSlider, RadioButtons
amplitude_slider = FloatSlider(min=0.1, max=1.0, step=0.1, value=0.2)
color_buttons = RadioButtons(options=['blue', 'green', 'red'])
# decorate the plot function with an environment from the UIs:
#interact(amplitude=amplitude_slider, color=color_buttons)
def plot(amplitude, color):
fig, ax = plt.subplots(figsize=(4, 3),
subplot_kw={'axisbg':'#EEEEEE',
'axisbelow':True})
ax.grid(color='w', linewidth=2, linestyle='solid')
x = np.linspace(0, 10, 1000)
ax.plot(x, amplitude * np.sin(x), color=color,
lw=5, alpha=0.4)
ax.set_xlim(0, 10)
ax.set_ylim(-1.1, 1.1)

Categories