FuncAnimation with a matrix - python

I would like to use FuncAnimation to animate a matrix that will evolve. I tried to use a very simple matrix before using a complex one but I don't manage to use FuncAnimation with the simple one. I tried looking on other posts but I can't adapt them to what I want to do. Here's what I tried to do but it doesn't work
from numpy import *
import matplotlib.pyplot as plt
import matplotlib.animation as animation
M=array([[0,0,100,100,100,100,100,100,300,300,300,300,300,300,500,500,500,500,500,500,1000,1000,1000,1000] for i in range(0,20)])
def update(i):
M[7,i] =1000
M[19-i,10]=500
mat.set_array(modif(i,M))
return mat
fig, ax = plt.subplots()
matrice = plt.matshow(mat)
plt.colorbar(matrice)
ani = animation.FuncAnimation(fig, update, frames=19, interval=1500)
plt.show()
I would just like to see the matrix moving to see its evolution.
If you have any ideas, please let me know (even if I'm a little inexperienced).
Thanks !

The reason your code doesn't work: You have not defined mat nor modif.
Also, you should plot to the axes (ax.matshow()) instead of creating a new plot (plt.matshow()).
The following should do what you want.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
M=np.array([[0,0,100,100,100,100,100,100,300,300,300,300,300,300,500,500,500,500,500,500,1000,1000,1000,1000] for i in range(0,20)])
def update(i):
M[7,i] = 1000
M[19-i,10] = 500
matrice.set_array(M)
fig, ax = plt.subplots()
matrice = ax.matshow(M)
plt.colorbar(matrice)
ani = animation.FuncAnimation(fig, update, frames=19, interval=500)
plt.show()

Related

General way to animate any artist in matplotlib?

I have tried to animate two different artists plt.quiver() and plt.hist() in matplotlib recently and both times I ran into the same problem. Apparently those classes (I hope my OOP literacy is holding up) both don't have a set_data like method. Well, technically plt.quiver() does have set_UVC, but that doesn't work with Line3D instances, only with Line2D. Also, there is an example for animating a histogram, but it seemed like some serious jerry-rigging to me. I tried to simply define my artist with new values in the update() function and then just return the new artist instead of defining the artist outside the update() and then updating the data of the artist using a set_data() method. But this only results in an animation in which all frames are kept in the plot and overlap. Below are the animations for both the Histogram and the Quiver plot.
Histogram:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
"""
evolution of mean values produced by 1000 dice rolls with
more and more dices, which lead to a narrowing variance
with a growing number of dices.
"""
fig, ax = plt.subplots()
def update(i):
k = [np.mean(np.random.randint(0,7,i)) for j in range(1000)]
lol = ax.hist(k,bins=20)
return lol
ani = FuncAnimation(fig, update, frames=(1,2,10,100,1000))
plt.show()
Quiver:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
def rot_z(angle):
o = 2*np.pi*(angle/360)
mat = np.array(((np.cos(o),-np.sin(o),0),
(np.sin(o), np.cos(o),0),
( 0 , 0 ,0)))
return mat
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(-1.5,1.5)
ax.set_ylim(-1.5,1.5)
ax.set_zlim(-1.5,1.5)
def update(frame):
x,y,z = rot_z(frame).dot(np.array((1,1,1)))
quiv = ax.quiver(0,
0,
0,
x,
y,
z,
length=1)
return quiv
ani = FuncAnimation(fig, update, frames=np.linspace(0,360,100))
plt.show()
If you run them, you can see the issue. So I wanted to know: Isn't there an easier, abstractable way of animating artists, or am I at the mercy of potentially non-existent setters? I have checked both dir(plt.quiver), dir(plt.hist) to see if I was simply overlooking those methods in the docs, but the example of the animated histogram seemed to confirm my fears.
You could try to clear the image at every update with ax.clear(). Maybe the histogram animation would be more smooth if you would extend an array of throws instead of restarting from scratch at each frame?
Edit: the code below includes a test to reuse the same samples
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
randnums = [np.random.randint(0,7,1000) for j in range(1000)]
def update(i):
k = [np.mean(randnums[j][:i]) for j in range(1000)]
ax.clear()
lol = ax.hist(k,bins=20)
return lol
ani = FuncAnimation(fig, update, frames=[2**t for t in range(11)])
plt.show()

Plot a rolling window with Matplotlib

I want to plot a time series in a while loop as a rolling window: The graph should always show the 10 most recent observations.
My idea was to use a deque object with maxlen=10 and plot it in every step.
To my great surprise the plot appends new values to the old plot; apparently it remembers values that are no longer inside the deque! Why is that and how can I switch it off?
This is a minimal example of what I am trying to do. The plotting part is based on this post (although plt.ion() did not change anything for me, so I left it out):
from collections import deque
import matplotlib.pyplot as plt
import numpy as np
x = 0
data = deque(maxlen=10)
while True:
x += np.abs(np.random.randn())
y = np.random.randn()
data.append((x, y))
plt.plot(*zip(*data), c='black')
plt.pause(0.1)
I also tried to use Matplotlib's animation functions instead, but could not figure out how to do that in an infinite while loop...
Nowadays, it's much easier (and offers much better performance) to use the animation module than to use multiple calls to plt.plot:
from collections import deque
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
def animate(i):
global x
x += np.abs(np.random.randn())
y = np.random.randn()
data.append((x, y))
ax.relim()
ax.autoscale_view()
line.set_data(*zip(*data))
fig, ax = plt.subplots()
x = 0
y = np.random.randn()
data = deque([(x, y)], maxlen=10)
line, = plt.plot(*zip(*data), c='black')
ani = animation.FuncAnimation(fig, animate, interval=100)
plt.show()

matplotlib FuncAnimation input [duplicate]

What I want to do is create an animation in which the nodes of a graph change color with time. When I search for information on animation in matplotlib, I usually see examples that look something like this:
#!/usr/bin/python
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation
fig = plt.figure(figsize=(8,8))
images = []
for i in range(10):
data = np.random.random(100).reshape(10,10)
imgplot = plt.imshow(data)
images.append([imgplot])
anim = ArtistAnimation(fig, images, interval=50, blit=True)
anim.save('this-one-works.mp4')
plt.show()
So I thought I could just do something like this:
#!/usr/bin/python
import numpy as np
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation
G = nx.Graph()
G.add_edges_from([(0,1),(1,2),(2,0)])
fig = plt.figure(figsize=(8,8))
pos=nx.graphviz_layout(G)
images = []
for i in range(10):
nc = np.random.random(3)
imgplot = nx.draw(G,pos,with_labels=False,node_color=nc) # this doesn't work
images.append([imgplot])
anim = ArtistAnimation(fig, images, interval=50, blit=True)
anim.save('not-this-one.mp4')
plt.show()
What I'm stuck on is how, after drawing the graph using nx.draw(), I can get an object of the appropriate type to put in the array being passed to ArtistAnimation. In the first example, plt.imshow() returns an object of type matplot.image.AxesImage, but nx.draw() doesn't actually return anything. Is there a way that I can get my hands on a suitable image object?
Completely different approaches are welcome, of course (it seems like there's always many different ways to do the same thing in matplotlib), as long as I can save my animation as an mp4 when I'm done.
Thanks!
--craig
import numpy as np
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
G = nx.Graph()
G.add_edges_from([(0,1),(1,2),(2,0)])
fig = plt.figure(figsize=(8,8))
pos=nx.graphviz_layout(G)
nc = np.random.random(3)
nodes = nx.draw_networkx_nodes(G,pos,node_color=nc)
edges = nx.draw_networkx_edges(G,pos)
def update(n):
nc = np.random.random(3)
nodes.set_array(nc)
return nodes,
anim = FuncAnimation(fig, update, interval=50, blit=True)
nx.draw does not return anything, hence why your method didn't work. The easiest way to do this is to draw the nodes and edges using nx.draw_networkx_nodes and nx.draw_networkx_edges which return PatchCollection and LineCollection objects. You can then update the color of the nodes using set_array.
Using the same general frame work you can also move the nodes around (via set_offsets for the PatchCollection and set_verts or set_segments for LineCollection)
best animation tutorial I have seen: http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/

Using NetworkX with matplotlib.ArtistAnimation

What I want to do is create an animation in which the nodes of a graph change color with time. When I search for information on animation in matplotlib, I usually see examples that look something like this:
#!/usr/bin/python
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation
fig = plt.figure(figsize=(8,8))
images = []
for i in range(10):
data = np.random.random(100).reshape(10,10)
imgplot = plt.imshow(data)
images.append([imgplot])
anim = ArtistAnimation(fig, images, interval=50, blit=True)
anim.save('this-one-works.mp4')
plt.show()
So I thought I could just do something like this:
#!/usr/bin/python
import numpy as np
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation
G = nx.Graph()
G.add_edges_from([(0,1),(1,2),(2,0)])
fig = plt.figure(figsize=(8,8))
pos=nx.graphviz_layout(G)
images = []
for i in range(10):
nc = np.random.random(3)
imgplot = nx.draw(G,pos,with_labels=False,node_color=nc) # this doesn't work
images.append([imgplot])
anim = ArtistAnimation(fig, images, interval=50, blit=True)
anim.save('not-this-one.mp4')
plt.show()
What I'm stuck on is how, after drawing the graph using nx.draw(), I can get an object of the appropriate type to put in the array being passed to ArtistAnimation. In the first example, plt.imshow() returns an object of type matplot.image.AxesImage, but nx.draw() doesn't actually return anything. Is there a way that I can get my hands on a suitable image object?
Completely different approaches are welcome, of course (it seems like there's always many different ways to do the same thing in matplotlib), as long as I can save my animation as an mp4 when I'm done.
Thanks!
--craig
import numpy as np
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
G = nx.Graph()
G.add_edges_from([(0,1),(1,2),(2,0)])
fig = plt.figure(figsize=(8,8))
pos=nx.graphviz_layout(G)
nc = np.random.random(3)
nodes = nx.draw_networkx_nodes(G,pos,node_color=nc)
edges = nx.draw_networkx_edges(G,pos)
def update(n):
nc = np.random.random(3)
nodes.set_array(nc)
return nodes,
anim = FuncAnimation(fig, update, interval=50, blit=True)
nx.draw does not return anything, hence why your method didn't work. The easiest way to do this is to draw the nodes and edges using nx.draw_networkx_nodes and nx.draw_networkx_edges which return PatchCollection and LineCollection objects. You can then update the color of the nodes using set_array.
Using the same general frame work you can also move the nodes around (via set_offsets for the PatchCollection and set_verts or set_segments for LineCollection)
best animation tutorial I have seen: http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/

Colormap issue using animation in matplotlib

I use matplotlib.animation to animate data in a 3D array named arr. I read data from a h5 file using h5py library and everything is OK. But when using animation, the colormap got stuck in first frame of the data range, and after some steps it shows unnormalized colors while plotting.
Here is my code:
import numpy as np
import h5py
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.cm as cm
f = h5py.File('ez.h5','r')
arr = f["ez"][:,:,:]
f.close()
fig = plt.figure()
i = 0
p = plt.imshow(arr[:,:,0], interpolation='bilinear', cmap=cm.RdYlGn)
def updatefig(*args):
global i
i += 1
if (i==333):
i = 0
p.set_array(arr[:,:,i])
plt.clim()
return p,
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
plt.show()
I think you want to replace set_clim() with
p.autoscale()
With no arguments, set_clim() is a no-op.
That said, changing your color scale in the middle of an animations seems very misleading.
You should also use set_data instead of set_array (according to the docs).

Categories

Resources