I am trying to animate the numpy array C3, this is an array with one channel of electrode data and I want to plot it in real time using matplotlib.
I have created my update function but nothing is printing out, I though the the syntax is you pass i through to loop through the plots and the FuncAnimation should do the rest.
Can someone please point me in the right direction?
Much appreciated!
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
data_skip = 50
def update_plot(i):
plt.cla()
plt.plot(C3[i:i+data_skip], t[i:i+data_skip])
plt.scatter(C3[i], t[i], marker='o', color='r')
plt.tight_layout()
plt.show()
ani = FuncAnimation(plt.gcf(), update_plot, interval=1000)
plt.tight_layout()
plt.show()
Remove plt.cla(), it will clear current axes. Every time you plot something on figure, plt.cla() then clears it.
You could confirm it by the following minimul example. It plots nothing
import matplotlib.pyplot as plt
import numpy as np
C3 = np.linspace(0.5, 10, 100)
t = np.linspace(0.5, 10, 100)
plt.plot(C3, t)
plt.cla()
plt.show()
Matplotlib documentation have an example to write animation code: simple_anim.py. You'd better explicitly declare fig and ax.
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import numpy as np
C3 = np.linspace(0.5, 10, 100)
t = np.linspace(0.5, 10, 100)
data_skip = 2
fig, ax = plt.subplots()
def update_plot(i):
ax.plot(C3[i:i+data_skip], t[i:i+data_skip])
ax.scatter(C3[i], t[i], marker='o', color='r')
ani = FuncAnimation(fig, update_plot, interval=1000)
plt.tight_layout()
plt.show()
Related
I'm new to python's matplotlib, and i want to animate a 1x1 square that moves diagonally across a grid space. I have written this bit of code that almost does what i want it to do, but the previous positions of the rectangle are still visible.
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
from matplotlib.patches import Rectangle
moving_block = [[0,0],[1,1],[2,2],[3,3],[4,4],[5,5]]
fig, ax = plt.subplots()
#set gridlines and lines every one unit
ax.grid(which='both')
ax.axis([0,5,0,5])
rectangle = Rectangle(moving_block[0], 1,1)
ax.add_patch(rectangle)
def animate(i):
ax.add_patch(Rectangle(moving_block[i], 1,1))
ani = matplotlib.animation.FuncAnimation(fig, animate,
frames=len(moving_block), interval=300, repeat=True)
plt.show()
How can i make only the current rectangle visible? Should i be using something other than this ax.add_patch(Rectangle) function?
Added cleaning "ax", at each iteration in the function "animate".
If you are satisfied with the answer, do not forget to vote for it :-)
import matplotlib.pyplot as plt
import matplotlib.animation
from matplotlib.patches import Rectangle
moving_block = [[0,0],[1,1],[2,2],[3,3],[4,4],[5,5]]
fig, ax = plt.subplots()
#set gridlines and lines every one unit
ax.grid(which='both')
ax.axis([0, 5, 0, 5])
rectangle = Rectangle(moving_block[0], 1,1)
ax.add_patch(rectangle)
def animate(i):
ax.clear()
ax.axis([0, 5, 0, 5])
ax.grid(which='both')
ax.add_patch(Rectangle(moving_block[i], 1,1))
ani = matplotlib.animation.FuncAnimation(fig, animate,
frames=len(moving_block), interval=300, repeat=True)
plt.show()
Im trying to annimate a kdeplot in python.
The idea is to evaluate actions over time.
The script below almost works as planned, but instead of updating the plot, it overlaps the plots and becomes very slow after a few runs.
So I can see that my problem might be that i dont really understand the animate func and have now becom very lost in trying to understand the problem.
So i hope that soembody can see the problem and help me.
import numpy as np
from matplotlib import animation
import matplotlib.pyplot as plt
import pandas as pd
import cmasher as cmr
from mplsoccer import VerticalPitch
df = pd.DataFrame(np.random.randint(0,100,size=(1000, 2)), columns=list('xy'))
#%%
pitch_dark = VerticalPitch(line_color='#cfcfcf', line_zorder=2, pitch_color='#122c3d')
fig, ax = pitch_dark.draw()
#kdeplot_dark = pitch_dark.kdeplot([], [], ax=ax, cmap=cmr.voltage, shade=True, levels=100)
def init():
kdeplot_dark = pitch_dark.kdeplot(0,0, ax=ax, cmap=cmr.voltage, shade=True, levels=100)
def animate(i):
x = df.x.iloc[i:i+20]
y = df.y.iloc[i:i+20]
kdeplot_dark = pitch_dark.kdeplot(x,y, ax=ax, cmap=cmr.voltage, shade=True, levels=100)
anim = animation.FuncAnimation(fig, animate, init_func=init)
plt.show()
I am trying to animate the wave function of electrons in an atom. I wrote the simplest python code following whats given in Matplotlob documentation on animation, but it does not do anything. Can anyone help?
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
import math
angles = (np.linspace(0, 2 * np.pi, 360, endpoint=False))
fig= plt.figure()
ax = fig.add_subplot(111, polar=True)
line1, =ax.plot([],[], 'g-', linewidth=1)
def update(theta):
line1.set_data(angles,energy_band(3, theta, 3))
return line1,
def init():
line1.set_data([],[])
return line1,
def energy_band(wave_number, phase_offset, energy_level):
return [math.sin(2*np.pi/360*i*wave_number+phase_offset*np.pi/360)+energy_level for i in range(360)]
ani = animation.FuncAnimation(fig, update, frames=[i for i in range(0,3600,5)], blit=True, interval=200, init_func=init)
plt.show()
The problem is with your data. Firstly, you must call set_data with single numeric. Secondly, if you divide energy function with 100 you have got data in a good scale to show. Moreover I set limits of axis. Check how I modify your code:
line1, =ax.plot([],[], 'ro')# 'g-', linewidth=1)
def update(theta):
line1.set_data(angles[int(theta)], energy_band(3, theta, 3)[int(theta)]/100)
#line1.set_data(angles,energy_band(3, theta, 3)/100)
return line1,
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
#line1.set_data([],[])
return line1,
Another thing is an interactive mode. It's usually a problem when matplotlib do nothing, especially working with jupyter notebook.
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
matplotlib.interactive(True)
plt.ion()
matplotlib.is_interactive()
The problem is that the data you want to animate lies between 2 and 4, but the polar plot shows only the range between -0.04 and 0.04. This is due to the use of an empty plot for the start. It would require you to set the limits manually. For example,
ax.set_rlim(0,5)
This is the only addition needed for your code to work.
However, one might optimize a bit more, e.g. use numpy throughout and reuse existing variables,
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
angles = (np.linspace(0, 2 * np.pi, 360, endpoint=False))
fig= plt.figure()
ax = fig.add_subplot(111, polar=True)
line1, =ax.plot([],[], 'g-', linewidth=1)
def update(theta):
line1.set_data(angles,energy_band(3, theta, 3))
return line1,
def init():
line1.set_data([],[])
ax.set_rlim(0,5)
return line1,
def energy_band(wave_number, phase_offset, energy_level):
return np.sin(angles*wave_number+phase_offset*np.pi/360)+energy_level
ani = animation.FuncAnimation(fig, update, frames=np.arange(0,3600,5),
blit=True, interval=200, init_func=init)
plt.show()
I'm trying to animate a curve in 3D and am having some trouble. I've successfully animated some things in 2D, so I thought I knew what I was doing. In the code below, I generate x, y, and z values parametrically to be a helix and have verified that I can plot the full curve in 3D. To animate the curve I am trying to begin by plotting only the first two data points and then use FuncAnimation to update the data so that it plots larger portions of the data. But as I said, it is not working for some reason and I have no idea why; all I get is the initial plot with the first two data points. Any help would be appreciated.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
t_max = 10
steps = 100
t = np.linspace(0, t_max, steps)
x = np.cos(t)
y = np.sin(t)
z = 0.1*t
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
line, = ax.plot(x[0:1], y[0:1], z[0:1])
def update(i):
line.set_xdata(x[0:i])
line.set_ydata(y[0:i])
line.set_zdata(z[0:i])
fig.canvas.draw()
ani = animation.FuncAnimation(fig, update, frames=t, interval=25, blit=False)
plt.show()
Okay, I finally got it to work. I had a dumb error (frames=t), but also figured out that you need to set the data in the update function differently. Here is the working code in case anyone is interested.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
t_max = 10
steps = 100
t = np.linspace(0, t_max, steps)
x = np.cos(t)
y = np.sin(t)
z = 0.1*t
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
line, = ax.plot([], [], [], lw=1)
ax.set_xlim(-1,1)
ax.set_ylim(-1,1)
ax.set_zlim(0,1)
plt.show()
def update(i):
line.set_data(x[0:i], y[0:i])
line.set_3d_properties(z[0:i])
return
ani = animation.FuncAnimation(fig, update, frames=100, interval=10, blit=True)
plt.show()
The code below creates an animation of 600k points by scatter plotting 30k of them per frame. The animation works flawlessly, except for the fact that I don't know how to include my colormap (Heatintensity) in the animation. The Xs and Ys are changing but the color of the points is just blue.
import numpy as np
import matplotlib.pyplot as plt
Heatintensity=workdata[0:600000] #Values controlling scatter colormap
Xs=xCoord[0:600000]
Ys=yCoord[0:600000]
plt.ion()
fig, ax = plt.subplots()
sc = ax.scatter(Xs, Ys, c=Heatintensity, cmap=cm.jet, s=5)
plt.draw()
for i in range(20):
sc.set_offsets(np.c_[Xs[(i*30000):(i*30000)+30000],\
Ys[(i*30000):(i*30000)+30000]])
fig.canvas.draw_idle()
plt.pause(0.1)
In order to change the colors, you need to use
sc.set_array(Heatintensity[(i*30000):(i*30000)+30000])
in addition to changing the offsets.
In order for the colors to represent the same numerical values for each animation step, the scatter must be normalized to all data,
norm = plt.Normalize(Heatintensity.min(), Heatintensity.max())
Complete example:
import numpy as np
import matplotlib.pyplot as plt
Heatintensity=np.random.rand(600000) #Values controlling scatter colormap
Xs=np.random.rand(600000)
Ys=np.random.rand(600000)
plt.ion()
fig, ax = plt.subplots()
norm = plt.Normalize(Heatintensity.min(), Heatintensity.max())
sc = ax.scatter(Xs, Ys, c=Heatintensity, s=5, cmap=plt.cm.jet, norm=norm)
plt.draw()
for i in range(20):
# set coordinates
sc.set_offsets(np.c_[Xs[(i*30000):(i*30000)+30000],\
Ys[(i*30000):(i*30000)+30000]])
# set colors
sc.set_array(Heatintensity[(i*30000):(i*30000)+30000])
# draw and make pause
plt.pause(0.1)
plt.ioff()
plt.show()
The same can be achieved using a FuncAnimation:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
Heatintensity=np.random.rand(600000) #Values controlling scatter colormap
Xs=np.random.rand(600000)
Ys=np.random.rand(600000)
fig, ax = plt.subplots()
norm = plt.Normalize(Heatintensity.min(), Heatintensity.max())
sc = ax.scatter(Xs, Ys, c=Heatintensity, s=5, cmap=plt.cm.jet, norm=norm)
def update(i):
# set coordinates
sc.set_offsets(np.c_[Xs[(i*30000):(i*30000)+30000],\
Ys[(i*30000):(i*30000)+30000]])
# set colors
sc.set_array(Heatintensity[(i*30000):(i*30000)+30000])
ani = animation.FuncAnimation(fig, update, frames=range(20), interval=100)
plt.show()