I have code for "live" plotting with Matplotlib in Python, but it closes once it's done. I would like the plot to remain open.
Code below
import time
import matplotlib.pyplot as plt
plt.ion()
plt.show()
for i in range(10):
time.sleep(1)
x = i ** 2
plt.scatter(i, x)
plt.draw()
Maybe you want something like this:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def make_data():
for i in range(100):
yield i, i*2
fig, ax = plt.subplots()
color = plt.cm.cubehelix(np.linspace(0.1,0.9,100))
plot, = ax.plot([], [],'o')
xdata, ydata = [], []
ax.set_ylim(0, 1)
ax.set_xlim(0, 1)
def run(data):
x,y = data
xdata.append(x)
ydata.append(y)
xmin, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
if y > ymax:
ax.set_xlim(xmin, 1+xmax)
ax.set_ylim(ymin, 1+ymax)
ax.figure.canvas.draw()
plot.set_color(color[x])
plot.set_data(xdata,ydata)
return plot,
ani = animation.FuncAnimation(fig,run,make_data,blit=True,interval=10,repeat=False)
plt.show()
Maybe scatter would be better since it might allow for different colors of each circle.
Related
I am trying to use Matplotlib to generate plot axes within a function called within a for-loop and use these axes to create a final multi-panel figure. However, despite the axes showing the proper lines when they are being created within my function, the multi-panel figure ends up with empty axes. What am I doing wrong? My code is below.
import numpy as np
import matplotlib.pyplot as plt
def create_axis(alpha, beta):
fig, ax = plt.subplots(figsize=(5, 4))
x = np.arange(10, dtype=float)
y = alpha + x * beta
ax.plot(x, y)
return ax
def create_plot():
alpha = 3.
axes_pool = []
for i in range(4):
axes_pool.append(create_axis(alpha, i))
fig, axes = plt.subplots(1, 4)
for i in range(len(axes)):
axes[i] = axes_pool[i]
plt.show()
if __name__ == '__main__':
create_plot()
You are passing the axes to the subfunction to allow the plt on the already created subplots.
Right approach is sending the axes as one of the parameters for create_axis function,which will plot the required data in the supplied axis.
import numpy as np
import matplotlib.pyplot as plt
def create_axis(ax,alpha, beta):
x = np.arange(10, dtype=float)
y = alpha + x * beta
ax.plot(x, y)
def create_plot():
alpha = 3.
fig, axes = plt.subplots(1, 4,figsize=(5,4)))
for i,ax in enumerate(axes):
create_axis(ax,alpha,i)
if __name__ == '__main__':
create_plot()
plt.show()
output:
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()
I plotted the picture using the code below.
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(6)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.set_xlim(0, 3)
ax.set_ylim(0, 10)
ax.plot(x, i * x)
plt.show()
This is the result picture.
enter image description here
This is the picture I want to see.
I want to get the results out of the box area.
How can you draw such a plot?
enter image description here
This should work -
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(6)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.set_xlim(0, 3)
ax.set_ylim(0, 10)
ax.plot(x, i * x)
if 3*i >10:
ytx = 10.5
xtx = 10.0/i
else:
ytx = 3*i
xtx = 3.05
tx = plt.text(xtx, ytx, str(i), fontsize=18, color='black')
plt.show()
This generates -
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()
I want to make 3D animation with matplotlib, but I don't know how to. Here is my non-working code.
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animation
from math import *
fig = plt.figure()
ax = fig.add_subplot(111) #, projection='3d'
#setting
ax.set_xlim(-5,5)
ax.set_ylim(-5,5)
#ax.set_zlim(-5,5)
ax.set_xlabel('x')
ax.set_ylabel('y')
#ax.set_zlabel('z')
ax.grid()
f1, = ax.plot([], [], "r-", lw=1) #plot1
def gen():
for phi in np.linspace(0,2*pi,100):
yield np.cos(phi), np.sin(phi), phi
def update(data):
p1, q1, psi = data
f1.set_data(p1,q1)
#f1.set_3d_properties(psi)
ani = animation.FuncAnimation(fig, update, gen, blit=False, interval=100, repeat=True)
#ani.save('matplot003.gif', writer='imagemagick')
plt.show()
I used this example http://matplotlib.org/1.4.1/examples/animation/simple_3danim.html
and modified your code:
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animation
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
def gen(n):
phi = 0
while phi < 2*np.pi:
yield np.array([np.cos(phi), np.sin(phi), phi])
phi += 2*np.pi/n
def update(num, data, line):
line.set_data(data[:2, :num])
line.set_3d_properties(data[2, :num])
N = 100
data = np.array(list(gen(N))).T
line, = ax.plot(data[0, 0:1], data[1, 0:1], data[2, 0:1])
# Setting the axes properties
ax.set_xlim3d([-1.0, 1.0])
ax.set_xlabel('X')
ax.set_ylim3d([-1.0, 1.0])
ax.set_ylabel('Y')
ax.set_zlim3d([0.0, 10.0])
ax.set_zlabel('Z')
ani = animation.FuncAnimation(fig, update, N, fargs=(data, line), interval=10000/N, blit=False)
#ani.save('matplot003.gif', writer='imagemagick')
plt.show()
Here is the following code for a sphere moving to the right and off the screen.
You will have to run this code in a folder for tidiness, as it generates 26 .png images (and a .gif image):
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from numpy import sin, cos, pi, outer, ones, size, linspace
# Define x, y, z lists for sphere
a = linspace(0, 2 * pi)
b = linspace(0, pi)
x = 10 * outer(cos(a), sin(b))
y = 10 * outer(sin(a), sin(b))
z = 10 * outer(ones(size(a)), cos(b))
# The amount of frames in the animation
frames = 26
# Generate each frame
for n in range(frames):
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x, y, z, color=('b'))
ax.set_xticks([])
ax.set_yticks([])
ax.set_zticks([])
ax.set_xlim(-8,8)
ax.set_xlim(-8,8)
ax.set_xlim(-8,8)
plt.savefig(f"{n}.png")
plt.close()
# Add 1 to the x so the sphere moves right by 1
x += 1
# Use pillow to save all frames as an animation in a gif file
from PIL import Image
images = [Image.open(f"{n}.png") for n in range(frames)]
images[0].save('ball.gif', save_all=True, append_images=images[1:], duration=100, loop=0)
Output: