Embedding Matplotlib Animations in Python (google colab notebook) - matplotlib

I am trying to show a gif file in google's colab.research. I was able to save the file in the directory with the following path name /content/BrowniamMotion.gif but I don't know how to show this GIF in my notebook to present.
The code to generate the GIF so far, in case someone can manipulate it not to save the GIF but rather to animate it directly into the google colab file was,
# Other Brownian Motion
from math import *
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import matplotlib.animation as animation
fig = plt.figure(figsize=(8,6))
ax = plt.axes(projection='3d')
N=10
#val1 = 500
x=500*np.random.random(N)
y=500*np.random.random(N)
z=500*np.random.random(N)
def frame(w):
ax.clear()
global x,y,z
x=x+np.random.normal(loc=0.0,scale=50.0,size=10)
y=y+np.random.normal(loc=0.0,scale=50.0,size=10)
z=z+np.random.normal(loc=0.0,scale=50.0,size=10)
plt.title("Brownian Motion")
ax.set_xlabel('X(t)')
ax.set_xlim3d(-500.0,500.0)
ax.set_ylabel('Y(t)')
ax.set_ylim3d(-500.0,500.0)
ax.set_zlabel('Z(t)')
ax.set_zlim3d(-500.0,500.0)
plot=ax.scatter
3D(x, y, z, c='r')
return plot
anim = animation.FuncAnimation(fig, frame, frames=100, blit=False, repeat=True)
anim.save('BrowniamMotion.gif', writer = "pillow", fps=10 )
Sorry if this question is badly, stated. I am new to Python and using colab research.

For Colab it is easiest to use 'jshtml' to display matplotlib animation.
You need to set it up with
from matplotlib import rc
rc('animation', html='jshtml')
Then, just type your animation object. It will display itself
anim
Here's a workable colab of your code.
It has a slider where you can run back and forth at any point in time.

Using the same authors git repository seems like we have a solution to embed the plots as GIFs ( Save Matplotlib Animations as GIFs ).
#!apt install ffmpeg
#!brew install imagemagick
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from IPython.display import HTML, Image # For GIF
rc('animation', html='html5')
np.random.seed(5)
# Set up formatting for the movie files
Writer = animation.writers['ffmpeg']
writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800)
def generateRandomLines(dt, N):
dX = np.sqrt(dt) * np.random.randn(1, N)
X = np.cumsum(dX, axis=1)
dY = np.sqrt(dt) * np.random.randn(1, N)
Y = np.cumsum(dY, axis=1)
lineData = np.vstack((X, Y))
return lineData
# Returns Line2D objects
def updateLines(num, dataLines, lines):
for u, v in zip(lines, dataLines):
u.set_data(v[0:2, :num])
return lines
N = 501 # Number of points
T = 1.0
dt = T/(N-1)
fig, ax = plt.subplots()
data = [generateRandomLines(dt, N)]
ax = plt.axes(xlim=(-2.0, 2.0), ylim=(-2.0, 2.0))
ax.set_xlabel('X(t)')
ax.set_ylabel('Y(t)')
ax.set_title('2D Discretized Brownian Paths')
## Create a list of line2D objects
lines = [ax.plot(dat[0, 0:1], dat[1, 0:1])[0] for dat in data]
## Create the animation object
anim = animation.FuncAnimation(fig, updateLines, N+1, fargs=(data, lines), interval=30, repeat=True, blit=False)
plt.tight_layout()
plt.show()
# Save as GIF
anim.save('animationBrownianMotion2d.gif', writer='pillow', fps=60)
Image(url='animationBrownianMotion2d.gif')
## Uncomment to save the animation
#anim.save('brownian2d_1path.mp4', writer=writer)

Check this link out on using the HTML to get it to work http://louistiao.me/posts/notebooks/embedding-matplotlib-animations-in-jupyter-notebooks/ .
I didn't embed a link but instead imbedded a HTML video that got it to work.
# Other Brownian Motion
from math import *
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import matplotlib.animation as animation
from IPython.display import HTML
fig = plt.figure(figsize=(8,6))
ax = plt.axes(projection='3d')
N=10
val1 = 600
x=val1*np.random.random(N)
y=val1*np.random.random(N)
z=val1*np.random.random(N)
def frame(w):
ax.clear()
global x,y,z
x=x+np.random.normal(loc=0.0,scale=50.0,size=10)
y=y+np.random.normal(loc=0.0,scale=50.0,size=10)
z=z+np.random.normal(loc=0.0,scale=50.0,size=10)
plt.title("Brownian Motion")
ax.set_xlabel('X(t)')
ax.set_xlim3d(-val1,val1)
ax.set_ylabel('Y(t)')
ax.set_ylim3d(-val1,val1)
ax.set_zlabel('Z(t)')
ax.set_zlim3d(-val1,val1)
plot=ax.scatter3D(x, y, z, c='r')
return plot
anim = animation.FuncAnimation(fig, frame, frames=100, blit=False, repeat=True)
anim.save('BrowniamMotion.gif', writer = "pillow", fps=10 )
HTML(anim.to_html5_video())
Essentially all we did hear was add,
from IPython.display import HTML to the premable and then add the line HTML(anim.to_html5_video()). This code then produces a video and saves the gif.

Related

Matplotlib video zooming and quality

I already figured out how to save a video animation and zooming a picture with matplotlib.
I want now to merge the two things and understand how to introduce zoom in an animation: reading some documentation I noticed it's not straightforward for just a picture, I expect to be the same or worse for a video.
In the following I write a simple working code, relating to that you can find on the first link
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
from matplotlib import cm
#Define x,y vectors and meshgrid with function u on it
x = np.arange(0,10,.1)
y = np.arange(0,10,.1)
X,Y = np.meshgrid(x,y)
#Create a figure and an axis object for the surface
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
#Animation without axes and with colormap
def animate(n):
ax.cla()
u = np.sin(X+Y+(n/10))
plt.axis('off')
plt.grid('off')
ax.plot_surface(X,Y,u,cmap=cm.inferno)
return fig,
anim = animation.FuncAnimation(fig,animate,frames=63)
anim.save('A.mp4',fps=20)
Here the output
As you can see is not bad zoomed, but it's not enough, I want it more!
In the actual code I'm using, video animations are very very small, and I don't know why because it's very similar to this. I hope also that this way I can increase video quality, that is quite poor.
Thanks for any help.
I finally got to a raw, but effective solution. The code almost doesn't change
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
from matplotlib import cm
#Define x,y vectors and meshgrid with function u on it
x = np.arange(0,10,.1)
y = np.arange(0,10,.1)
X,Y = np.meshgrid(x,y)
#Create a figure and an axis object for the surface
fig = plt.figure(frameon=False)
ax = fig.add_subplot(111,projection='3d')
#Definition? and zooming
fig.set_size_inches(10,10)
fig.subplots_adjust(left=0,right=1,bottom=0,top=1,wspace=None,hspace=None)
#Animation without axes and with colormap
def animate(n):
ax.cla()
u = np.sin(X+Y+(n/10))
plt.axis('off')
plt.grid('off')
ax.plot_surface(X,Y,u,cmap=cm.inferno)
print(n)
return fig,
anim = animation.FuncAnimation(fig,animate,frames=63)
anim.save('A.gif',fps=20)
As you can see the zooming is good.
The bad quality is due to compression I did in a second moment, because the actual output gif is quite heavy with those parameters, in fact the quality is very good.

How to draw graphics dynamically on jupyterlab notebook

I found an example that can run normally on my laptop, but there is a problem. When the drawing is finished, a repeated result graph will be drawn again. I want to know how to not display the last repeated image.
import numpy as np
import matplotlib
%matplotlib inline
import matplotlib.pyplot as plt
# set up matplotlib
is_ipython = 'inline' in matplotlib.get_backend()
if is_ipython:
from IPython import display
plt.ion()
def plot_durations(y):
plt.figure(2)
plt.clf()
plt.subplot(211)
plt.plot(y[:,0])
plt.subplot(212)
plt.plot(y[:,1])
if is_ipython:
display.clear_output(wait=True)
display.display(plt.gcf())
x = np.linspace(-10,10,10)
y = []
for i in range(len(x)):
y1 = np.cos(i/(3*3.14))
y2 = np.sin(i/(3*3.14))
y.append(np.array([y1,y2]))
plot_durations(np.array(y))
plt.ioff()
plt.show()
Replacing plt.show() with plt.close() at the end of your code will prevent jupyter notebook from displaying the final plot twice. An explanation is included here.

How to use plt.savefig() without using plt.show() and the end of matplotlib.animation.FuncAnimation

For example, this code works fine and saves the plt only when the plt.show() is present at the end. or else it just runs without saving any output.
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
def animate(i):
line.set_ydata(np.sin(2*np.pi*i / 50)*np.sin(x))
#fig.canvas.draw() not needed see comment by #tacaswell
plt.savefig(str(i)+".png")
return line,
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1,1)
x = np.linspace(0, 2*np.pi, 200)
line, = ax.plot(x, np.zeros_like(x))
plt.draw()
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=5, repeat=False)
plt.show()
PS - I tried using ani.save(writer="ffmpeg",dpi=200) and it works fine, but later on as I am using ffmpeg commands to convert the image sequence to animation, it shows invalid PNG signature.
Also I am new in this field so my appoligies if i did not follow any proper method.
Thanks in advance.

updated graphs through iteration, matplotlib

I'm trying to graph features of a data-set one by one by, via iteration.
So I want the graph to continuously update as I proceed through the loop.
I refered to this thread,real-time plotting in while loop with matplotlib but the answers are all over the place, and despite incorporating some of their suggestions as shown below, I still can't seem to get the code working. I'm using Jupyter Notebook.
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
colors = ["darkblue", "darkgreen"]
f, (ax1, ax2) = plt.subplots(1, 2, sharey=True, sharex = True)
for i in range(X.shape[-1]-1):
idx = np.where(y == 1)[0]
ax1.scatter(X[idx, i], X[idx, i+1], color=colors[0], label=1)
idx = np.where(y == 0)[0]
ax2.scatter(X[idx, i], X[idx, i+1], color=colors[1], label=0)
plt.draw()
plt.pause(0.0001)
Any suggestions?
Thank you.
This is an example for real-time plotting in a Jupyter Notebook
%matplotlib inline
%load_ext autoreload #Reload all modules every time before executing the Python code typed.
%autoreload 2
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
import time
colors = ["darkblue", "darkgreen"]
# initialise the graph and settings
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = fig.add_subplot(211)
plt.ion() # interactive mode
fig.show()
fig.canvas.draw() # matplotlib canvas drawing
# plotting loop
for i in range(X.shape[-1]-1):
ax1.clear()
ax2.clear()
idx = np.where(y == 1)[0]
ax1.scatter(X[idx, i], X[idx, i+1], color=colors[0], label=1)
idx = np.where(y == 0)[0]
ax2.scatter(X[idx, i], X[idx, i+1], color=colors[1], label=0)
fig.canvas.draw() # draw
time.sleep(0.5) # sleep
For an animation you need an interactive backend. %matplotlib inline is no interactive backend (it essentially shows a printed version of the figure).
You may decide not to run you code in jupyter but as a script. In this case you would need to put plt.ion() to put interactive mode on.
Another option would be to use a FuncAnimation, as e.g in this example. To run such a FuncAnimation in Jupyter you will still need some interactive backend, either %matplotlib tk or %matplotlib notebook.
From matplotlib 2.1 on, we can also create an animation using JavaScript.
from IPython.display import HTML
HTML(ani.to_jshtml())
Some complete example:
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()
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))
from IPython.display import HTML
HTML(ani.to_jshtml())

Matplotlib animation not working in IPython Notebook (blank plot)

I've tried multiple animation sample codes and cannot get any of them working. Here's a basic one I've tried from the Matplotlib documentation:
"""
A simple example of an animated plot
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
x = np.arange(0, 2*np.pi, 0.01) # x-array
line, = ax.plot(x, np.sin(x))
def animate(i):
line.set_ydata(np.sin(x+i/10.0)) # update the data
return line,
#Init only required for blitting to give a clean slate.
def init():
line.set_ydata(np.ma.array(x, mask=True))
return line,
ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), init_func=init,
interval=25, blit=True)
plt.show()
When I execute the above in an IPython Notebook, I just see a blank plot generated. I've tried running this from multiple servers (including Wakari), on multiple machines, using multiple browsers (Chrome, FF, IE).
I can save the animation to an mp4 file just fine and it looks good when played.
Any help is appreciated!
To summarize the options you have:
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:
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())
According to this answer, you can get animation (and full interactivity support) working in an IPython notebook enabling the nbagg backend with %matplotlib nbagg.
I was having the exact same problem as you until a moment ago. I am a complete novice, so tcaswell's answer was a bit cryptic to me. Perhaps you figured out what he meant or found your own solution. In case you have not, I will put this here.
I googled "matplotlib inline figures" and found this site, which mentions that you have to enable matplotlib mode. Unfortunately, just using %maplotlib didn't help at all.
Then I typed %matplotlib qt into the IPython console on a lark and it works just fine now, although the plot appears in a separate window.
I ran into this issue as well and found I needed to understand the concept of matplotlib backends, how to enable a specific backend, and which backends work with FuncAnimation. I put together an ipython notebook that explains the details and summarizes which backends work with FuncAnimation on Mac, Windows, and wakari.io. The notebook also summarizes which backends work with the ipython interact() widget, and where plots appear (inline or secondary window) for basic matplotlib plotting. Code and instructions are included so you can reproduce any of the results.
The bottom line is that you can't get an animation created with FuncAnimation to display inline in an ipython notebook. However, you can get it to display in a separate window. It turns out that I needed this to create visualizations for an undergraduate class I am teaching this semester, and while I would much prefer the animations to be inline, at least I was able to create some useful visualizations to show during class.
No inline video in Jupyter at the end of an animation also happens when
HTML(ani.to_html5_video())
is not at the very end of a notebook cell, as the output is then suppressed.
You may use it then as follows
out = HTML(ani.to_html5_video())
and just type out` in a new cell to get the video online.