I've got some code similar to this
from matplotlib import animation
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
def animate(i):
x0,y0 = np.random.random(size=(2,))*4-2
x = np.random.normal(loc=x0, size=(1000,))
y = np.random.normal(loc=y0, size=(1000,))
for layer in prevlayers:
layer.remove()
prevlayers[:] = []
hexlayer = ax.hexbin(x,y, gridsize=10, alpha=0.5)
# the following line is needed in my code
hexlayer.remove()
prevlayers.append(hexlayer)
return hexlayer,
prevlayers = []
ani = animation.FuncAnimation(fig, animate, frames=12)
ani.save('teste.gif', writer='PillowWriter')
I'm trying to show only one frame at a time, but the code that I have written uses two ax.hexbin() calls and I have to remove one of them in order to show the correct graph. Is there a way to show one hexbin layer at a time using FuncAnimation?
You only need ax.clear() for each frame
from matplotlib import animation
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
def animate(i):
ax.clear()
x0,y0 = np.random.random(size=(2,))*4-2
x = np.random.normal(loc=x0, size=(1000,))
y = np.random.normal(loc=y0, size=(1000,))
hexlayer = ax.hexbin(x,y, gridsize=10, alpha=0.5)
return ax
ani = animation.FuncAnimation(fig, animate, frames=12)
ani.save('teste.gif', writer='PillowWriter')
this code produces
Related
I have used .set_data() method/function to update co-ordinate of the line after every frame. x1,y1 values are being updated but they are not being update in the line plot. What am I doing wrong here?
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(6,6)
ax=plt.axes(xlim=(-10,10), ylim=(-10,10))
l1, = ax.plot([0.0, 1.0],[0.0,5.0], color = 'b', linewidth = 1)
def animate(i):
x1=np.sin(np.radians((i)+90))
y1=np.cos(np.radians((i)+90))
l1.set_data=([0,x1],[0,y1])
#print (x1,y1)
return l1,
anim = animation.FuncAnimation(fig, animate, frames=360, interval=20, blit=True)
plt.show()
You wrote l1.set_data=([0,x1],[0,y1]). Is that a typo? This should be (notice the removal of the = sign):
l1.set_data([0,x1],[0,y1])
When I run this Python program the x and y axes scale adjusts as more data gets plotted. Is it possible to set a scale to which the chart will be created to and have it not change during excution? I had tried plt.xlim(0, 30) and plt.ylim(0, 1050) but it made no difference.
import numpy as np
from itertools import count
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
plt.style.use('fivethirtyeight')
data = pd.read_csv('csv_data.csv')
x_vals = []
y_vals1 = []
y_vals2 = []
index = count()
def animate(i):
x = data['x_value']
y1 = data['total_1']
y2 = data['total_2']
x_vals = x[0:i]
y_vals1 = y1[0:i]
y_vals2 = y2[0:i]
plt.cla()
plt.plot(x_vals, y_vals1, label='Channel 1')
plt.plot(x_vals, y_vals2, label='Channel 2')
plt.legend(loc='upper left')
plt.tight_layout()
ani = FuncAnimation(plt.gcf(), animate, frames=len(data.index) -1, interval=100, repeat = False)
plt.show()
Add the following lines after plt.cla:
plt.xlim(0, 27)
plt.ylim(900, 1050)
I am trying to construct a live graph in python to plot random numbers in a graph with a fixed plot window
The width of the plot window will be 20 samples. For the 21st sample, the 1st sample will dissappear from the right side. Here is my code. Cant figure out why is it not plotting.
import random
import time
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
#creating a subplot
ax1 = fig.add_subplot(1,1,1)
xs = []
ys = []
iter = 0
def animate(i,xs,ys,iter):
while True:
iter = iter+1
xs.append(iter)
ys.append(round(random.uniform(-120,20),2))
#I want only 20 data points on the plot i.e the plot window will be only showing 20 samples at a time
x = xs[-20:]
y = ys[-20:]
ax1.clear()
ax1.plot(x, y)
ax1.set_ylim([-120,20])
plt.xlabel('Value')
plt.ylabel('Time')
plt.title('Live Graph')
time.sleep(1)
ani = animation.FuncAnimation(fig, animate, fargs = (xs,ys,iter), interval=1000)
plt.show()
Check out the documentation for FuncAnimation.
The second parameter is a function that is repeatedly called for each consecutive frame, updating the figure with each call. Your function animate is an infinite loop, so the execution thread never returns back to FuncAnimation. Try something like this instead as a starting point:
import random
import time
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
xs = []
ys = []
line, = ax1.plot(xs, ys)
plt.xlabel('Value')
plt.ylabel('Time')
plt.title('Live Graph')
def animate(frame, xs, ys):
xs.append(frame)
ys.append(round(random.uniform(-120,20),2))
x = xs[-20:]
y = ys[-20:]
line.set_xdata(x)
line.set_ydata(y)
ax1.set_xlim(min(x)-1, max(x)+1)
ax1.set_ylim(min(y)-1, max(y)+1)
ax1.set_xticks(list(range(min(x), max(x)+1)))
return line
ani = animation.FuncAnimation(fig, animate, fargs = (xs,ys), interval=100)
plt.show()
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure(1)
ax1 = fig.add_subplot(1,1,1)
def animate(i):
graph_data = open('example.txt','r').read()
lines = graph_data.split('\n')
xs = []
ys = []
for line in lines:
if len(line) > 1:
x, y = line.split(',')
xs.append(x)
ys.append(y)
ax1.clear()
ax1.plot(xs, ys)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
Is there another way to write the code such that y-axis is in ascending order?
If so. where should I find it? This is from sentdex matplotlib tutorial
The better solution is to not do all the stuff manually and rely on numpy reading the data. Also, not clearing the axes in each loopstep may be beneficial.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
line, = ax.plot([],[])
def animate(i):
x,y = np.loadtxt("data/example.txt", unpack=True, delimiter=",")
line.set_data(x,y)
ax.relim()
ax.autoscale_view()
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
I am relatively new to python (coming from Matlab). As one project, I am trying to create an animated plot of a correlation matrix over time. To make the plots nice, I am trying seaborn. I struggled to get the animation done at all (having issues with Matplotlib backend on a mac), but a very basic animation now works using this code from the web:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
nx = 50
ny = 50
fig = plt.figure()
data = np.random.rand(nx, ny)
im = plt.imshow(data)
def init():
im.set_data(np.zeros((nx, ny)))
def animate(i):
#xi = i // ny
#yi = i % ny
data = np.random.rand(nx, ny)
im.set_data(data)
return im
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=50, repeat = False)
Now, I was trying to adapt this to seaborn, but did not succeed. It seems that seaborn works on subplots and to animate these was far harder. The best thing I got once was a kind of recursive plot, where seaborn.heatmaps were plotted on top of each other. Also, the im.set_data method was not available.
Any suggestions are highly appreciated.
I replaced plt.imshow (casting data via set_data didn't work) with seaborn.heatmap.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import animation
fig = plt.figure()
data = np.random.rand(10, 10)
sns.heatmap(data, vmax=.8, square=True)
def init():
sns.heatmap(np.zeros((10, 10)), vmax=.8, square=True, cbar=False)
def animate(i):
data = np.random.rand(10, 10)
sns.heatmap(data, vmax=.8, square=True, cbar=False)
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=20, repeat = False)
This creates the recursive plot I struggled with.
In addition to your answer above, I wanted to do this from a list of dataframes and save as a gif. So, using your code and Serenity's answer to Matplotlib animation iterating over list of pandas dataframes
fig = plt.figure()
def init():
sns.heatmap(np.zeros((10, 10)), vmax=.8, square=True, cbar=False)
def animate(i):
data = data_list[i]
sns.heatmap(data, vmax=.8, square=True, cbar=False)
data_list = []
for j in range(20):
data = np.random.rand(10, 10)
data_list.append(data)
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=20, repeat = False)
savefile = r"test3.gif"
pillowwriter = animation.PillowWriter(fps=20)
anim.save(savefile, writer=pillowwriter)
plt.show()
Thanks!!!
Here's a complete example (tested with Matplotlib 3.0.3).
import matplotlib.animation as animation
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
def animate_heat_map():
fig = plt.figure()
nx = ny = 20
data = np.random.rand(nx, ny)
ax = sns.heatmap(data, vmin=0, vmax=1)
def init():
plt.clf()
ax = sns.heatmap(data, vmin=0, vmax=1)
def animate(i):
plt.clf()
data = np.random.rand(nx, ny)
ax = sns.heatmap(data, vmin=0, vmax=1)
anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1000)
plt.show()
if __name__ == "__main__":
animate_heat_map()
Based on the answer of r schmaelzle I created animated seaborn heatmap with annotaion.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import animation
class Heatmap:
def __init__(self):
self.fig, self.ax = plt.subplots()
self.anim = None
def animate(self):
def init():
sns.heatmap(np.zeros((10, 10)), vmax=.8, ax=self.ax)
def animate(i):
self.ax.texts = []
sns.heatmap(np.random.rand(10, 10), annot=True, vmax=.8, cbar=False, ax=self.ax)
self.anim = animation.FuncAnimation(self.fig, animate, init_func=init, frames=20, repeat=False)
if __name__ == '__main__':
hm = Heatmap()
hm.animate()
The trick to update annotations is to make empty ax.texts = [].
I hope it will help others! :)