Matplotlib animation save does not create animation for surface plots - python

I am trying to use matplotlib.animation to animate the time evolution of a surface. A working example is found on this stackexchange question/answer. Using plt.show() I can see the animation fine. The problem is when I try to save it. When saving as either a gif or mp4 I get only one from of the animation. I do not get this problem if I am doing 1d animations, for example using plt.plot(). Below is what I am trying:
from mpl_toolkits.mplot3d import axes3d
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import cm
def generate(X, Y, phi):
R = 1 - np.sqrt(X**2 + Y**2)
return np.cos(2 * np.pi * X + phi) * R
fig = plt.figure()
ax = axes3d.Axes3D(fig)
xs = np.linspace(-1, 1, 50)
ys = np.linspace(-1, 1, 50)
X, Y = np.meshgrid(xs, ys)
Z = generate(X, Y, 0.0)
wframe = ax.plot_surface(X, Y, Z, rstride=2, cstride=2, cmap=cm.coolwarm )
ax.set_zlim(-1,1)
def update(i, ax, fig):
ax.cla()
phi = i * 360 / 2 / np.pi / 100
Z = generate(X, Y, phi)
wframe = ax.plot_surface( X, Y, Z, rstride=2,
cstride=2, cmap=cm.coolwarm )
ax.set_zlim(-1,1)
return wframe,
ani = animation.FuncAnimation( fig, update, frames=10,
fargs=(ax, fig), interval=100 )
ani.save('plottest3d2.mp4', fps=30)
ani.save('plottest3d3.gif', fps=30, writer='imagemagick')
plt.show()
Any help explaining the discrepancy between showing the plot and saving would be great.

Related

How can I create a graph from an equation with two unknowns with python?

I want to create a probably plot with a equation and two unknowns but I didn't success...
Here is my script
from numpy import exp, sqrt, linspace
from matplotlib import pyplot as plt
from pylab import meshgrid, cm, imshow, contour, clabel, colorbar, axis, title, show
plt.rcParams["figure.figsize"] = [10, 5]
plt.rcParams["figure.autolayout"] = True
def f(x, y):
return (1 / sqrt(x)) * exp(-y / 50) * (1 - exp(-x / 1097) * (2 * exp(-y / (2 * 50)) - 1))
x = linspace(10, 1000, 990)
y = linspace(10, 50, 40)
X, Y = meshgrid(x, y)
Z = f(X, Y)
Thank you so much !!
I would like to have a x value between 10 and 1000 and y value between 10 and 50 for example. And obtain this kind of plot.
As explained in This Link You can use matplotlibs 3d plotting api. Here's an example:
fig = plt.figure()
ax = plt.axes(projection='3d')
plt.xlim(10, 1000)
plt.ylim(10, 50)
# Some Different Types of Plots That You can Use:
ax.scatter3D(X, Y, Z, c=Z, cmap='Greens')
# ax.plot_wireframe(X, Y, Z, color='black')
# ax.plot3D(X.flatten(), Y.flatten(), Z.flatten())
# ax.contour3D(X, Y, Z, 990, cmap='binary')
plt.savefig('test.png')

Output matplotlib plots from saving

I found a tutorial online for this matplotlib and numpy graph. The code runs smoothly, but there is no output. I have tried to save the graph as a file, but that does not seem to work.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
fig = plt.figure()
ax = plt.axes(projection="3d")
zline = np.linspace(0, 15, 1000)
xline = np.sin(zline)
yline = np.cos(zline)
ax.plot3D(xline, yline, zline, "gray") # Data for three-dimensional scattered points
zdata = 15 * np.random.random(100)
xdata = np.sin(zdata) + 0.1 * np.random.randn(100)
ydata = np.cos(zdata) + 0.1 * np.random.randn(100)
ax.scatter3D(xdata, ydata, zdata, c=zdata, cmap="Greens");
def f(x, y):
return np.sin(np.sqrt(x ** 2 + y ** 2))
x = np.linspace(-6, 6, 30)
y = np.linspace(-6, 6, 30)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 50, cmap='binary')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z');
theta = 2 * np.pi * np.random.random(1000)
r = 6 * np.random.random(1000)
x = np.ravel(r * np.sin(theta))
y = np.ravel(r * np.cos(theta))
z = f(x, y)
ax = plt.axes(projection="3d")
ax.plot_trisurf(x, y, z,cmap="viridis", edgecolor="none");
The link to the website is https://www.edureka.co/blog/python-projects/. Surely there is some way to access the graphical user interface to display the plots?
Adding plt.show() at the end will display both of the graphs.

imshow with colorbars using Matplotlib animation of subplots

I am trying to figure out how to animate 3 subplots using matplotlib.animation. My code is looking like this:
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, sharex='col', sharey='row')
ax1.set_aspect('equal', 'datalim')
ax1.set_adjustable('box-forced')
ax2.set_aspect('equal', 'datalim')
ax2.set_adjustable('box-forced')
ax3.set_aspect('equal', 'datalim')
ax3.set_adjustable('box-forced')
#fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
def g(x, y):
return np.sin(x) + 0.5*np.cos(y)
def h(x, y):
return 0.5*np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
im1 = plt.imshow(f(x, y), cmap=plt.get_cmap('viridis'), animated=True)
plt.colorbar(im1)
im2 = plt.imshow(g(x, y), cmap=plt.get_cmap('viridis'), animated=True)
plt.colorbar(im2)
im3 = plt.imshow(h(x, y), cmap=plt.get_cmap('viridis'), animated=True)
plt.colorbar(im3)
def updatefig(*args):
global x, y
x += np.pi / 15.
y += np.pi / 20.
im1.set_array(f(x, y))
im2.set_array(g(x, y))
im3.set_array(h(x, y))
return im1,im2,im3
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
#plt.colorbar()
plt.show()
First thing - why don't I see the other two plots than im1?
Second thing - how can I add the colorbars correctly to each one of the subplots?
This is happening because you are not referencing the other ax objects you created. Thus you keep referencing the same set axes. Same story with the color bars as well. You are pretty close you just need to point everything to the right object, have a look.
im1 = ax1.imshow(f(x, y), cmap=plt.get_cmap('viridis'), animated=True)
fig.colorbar(im1,ax=ax1)
im2 = ax2.imshow(g(x, y), cmap=plt.get_cmap('viridis'), animated=True)
fig.colorbar(im2,ax=ax2)
im3 = ax3.imshow(h(x, y), cmap=plt.get_cmap('viridis'), animated=True)
fig.colorbar(im3,ax=ax3)
Single snap shot of 3 animate plots

Beginner-Make a frame based video in python from figures

I plot figures in a for loop which is a loop for my time, basically at each time step I plot a surf out of my data as below:
for time_step in range(0,nt):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = np.arange(xmin, xmax+dx, dx)
z = np.arange(zmin, zmax+dz, dz)
X, Z = np.meshgrid(x, z)
ax.plot_surface(X, Z, w1[time_step])
plt.show()
Suppose that w1[time_step] changes in the loop and is sth different at each time step, all other assumptions you can have. I plot but don't know only how to make them into a video.
I have done it matlab, but I want to do sth similar in Python
Matplotlib as some animation features you might want to use. Check the following recipe (that I collected from here):
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
import time
def generate(X, Y, phi):
R = 1 - np.sqrt(X**2 + Y**2)
return np.cos(2 * np.pi * X + phi) * R
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
xs = np.linspace(-1, 1, 50)
ys = np.linspace(-1, 1, 50)
X, Y = np.meshgrid(xs, ys)
Z = generate(X, Y, 0.0)
wframe = None
tstart = time.time()
for phi in np.linspace(0, 360 / 2 / np.pi, 100):
oldcol = wframe
Z = generate(X, Y, phi)
wframe = ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2)
# Remove old line collection before drawing
if oldcol is not None:
ax.collections.remove(oldcol)
plt.pause(.001)
print('FPS: %f' % (100 / (time.time() - tstart)))
Just replace the wireframe plot for whatever you want (and also use your data obviously) and you should have what you are looking for.

Adding errorbars to 3D plot in matplotlib

I can't find a way to draw errorbars in a 3D scatter plot in matplotlib.
Basically, for the following piece of code
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X, Y, Z = axes3d.get_test_data(1)
ax.scatter(X, Y, zs = Z, zdir = 'z')
I am looking for something like
ax.errorbar(X,Y, zs = Z, dY, dX, zserr = dZ)
Is there a way to do this in mplot3d? If not, are there other libraries with this function?
There is clearly example on forum http://mple.m-artwork.eu/home/posts/simple3dplotwith3derrorbars
Here is the code but is not built-in functionality:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as axes3d
fig = plt.figure(dpi=100)
ax = fig.add_subplot(111, projection='3d')
#data
fx = [0.673574075,0.727952994,0.6746285]
fy = [0.331657721,0.447817839,0.37733386]
fz = [18.13629648,8.620699842,9.807536512]
#error data
xerror = [0.041504064,0.02402152,0.059383144]
yerror = [0.015649804,0.12643117,0.068676131]
zerror = [3.677693713,1.345712547,0.724095592]
#plot points
ax.plot(fx, fy, fz, linestyle="None", marker="o")
#plot errorbars
for i in np.arange(0, len(fx)):
ax.plot([fx[i]+xerror[i], fx[i]-xerror[i]], [fy[i], fy[i]], [fz[i], fz[i]], marker="_")
ax.plot([fx[i], fx[i]], [fy[i]+yerror[i], fy[i]-yerror[i]], [fz[i], fz[i]], marker="_")
ax.plot([fx[i], fx[i]], [fy[i], fy[i]], [fz[i]+zerror[i], fz[i]-zerror[i]], marker="_")
#configure axes
ax.set_xlim3d(0.55, 0.8)
ax.set_ylim3d(0.2, 0.5)
ax.set_zlim3d(8, 19)
plt.show()
I ended up writing the method for matplotlib: official example for 3D errorbars:
import matplotlib.pyplot as plt
import numpy as np
ax = plt.figure().add_subplot(projection='3d')
# setting up a parametric curve
t = np.arange(0, 2*np.pi+.1, 0.01)
x, y, z = np.sin(t), np.cos(3*t), np.sin(5*t)
estep = 15
i = np.arange(t.size)
zuplims = (i % estep == 0) & (i // estep % 3 == 0)
zlolims = (i % estep == 0) & (i // estep % 3 == 2)
ax.errorbar(x, y, z, 0.2, zuplims=zuplims, zlolims=zlolims, errorevery=estep)
ax.set_xlabel("X label")
ax.set_ylabel("Y label")
ax.set_zlabel("Z label")
plt.show()

Categories

Resources