Matplotlib append to z axis - python

I want to plot in 3D using matplotlib (python), which data is added in real time(x,y,z).
In the below code, data appends on x-axis and y-axis successfully, but on z-axis I've encountered problems.although I've searched in matplotlib's docs, I could not find any solutions.
what should be added/changed to this code to make it append data in z-axis?
what works correctly:
return plt.plot(x, y, color='g')
problem:
return plt.plot(x, y, z, color='g')
Code:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
import random
np.set_printoptions(threshold=np.inf)
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
x = []
y = []
z = []
def animate(i):
x.append(random.randint(0,5))
y.append(random.randint(0,5))
z.append(random.randint(0,5))
return plt.plot(x, y, color='g')
#return plt.plot(x, y, z, color='g') => error
ani = animation.FuncAnimation(fig, animate, interval=1000)
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_zlabel('z')
plt.show()
How to get this done correctly?

The plotting method you want to use for 3D plots is the one from the Axes3D. Hence you need to plot
ax1.plot(x, y, z)
However, it seems you want to update the data instead of plotting it all over again (making the line look somehow rasterized, as it would consists of all the plots).
So you can use set_data and for the third dimension set_3d_properties. Updating the plot would look like this:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
x = []
y = []
z = []
line, = ax1.plot(x,y,z)
def animate(i):
x.append(np.random.randint(0,5))
y.append(np.random.randint(0,5))
z.append(np.random.randint(0,5))
line.set_data(x, y)
line.set_3d_properties(z)
ani = animation.FuncAnimation(fig, animate, interval=1000)
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_zlabel('z')
ax1.set_xlim(0,5)
ax1.set_ylim(0,5)
ax1.set_zlim(0,5)
plt.show()

Related

Plotting vertical lines in matplotlib.animation over a scatter plot

I am wanting to use matplotlib.annimation to sequentially plot data points and plot vertical lines as they become known.
What I have at the moment is the following:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
x = np.arange(len(data))
y = data
fig = plt.figure()
plt.xlim(0, len(data))
plt.ylim(-8, 8)
graph, = plt.plot([], [], 'o')
def animate(i):
# line_indicies = func(x[:i+1])
graph.set_data(x[:i+1], y[:i+1])
# then I would like something like axvline to plot a vertical line at the indices in line indices
return graph
anim = FuncAnimation(fig, animate, frames=100, interval=200)
# anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
plt.show()
I would like to plot vertical lines outputted from a function as described in the comments in the animate function.
The lines are subject to change as more data points are processed.
I wrote the code with the understanding that I wanted to draw a vertical line along the index of the line graph. I decided on the length and color of the vertical line, and wrote the code in OOP style, because if it is not written in ax format, two graphs will be output.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
data = np.random.randint(-8,8,(100,))
x = np.arange(len(data))
y = data
fig = plt.figure()
ax = plt.axes(xlim=(0, len(data)), ylim=(-8, 8))
graph, = ax.plot([], [], 'o')
lines, = ax.plot([],[], 'r-', lw=2)
def init():
lines.set_data([],[])
return
def animate(i):
graph.set_data(x[:i+1], y[:i+1])
# ax.axvline(x=i, ymin=0.3, ymax=0.6, color='r', lw=2)
lines.set_data([i, i],[-3, 2])
return graph
anim = FuncAnimation(fig, animate, frames=100, interval=200)
# anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
plt.show()

Why simple animation code for my wave function does not work?

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()

How do i make y-axis to be in an ascending order in matplotlib.animation? Sentdex tutorial

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()

Trouble animating a 3D plot in python

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()

How to set a colormap in interactive plot animations in python

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()

Categories

Resources