4
$\begingroup$

I'm trying to get an animated 2D data surface on MatPlotLib. After a bit of search on the internet, i've found an example that almost works:

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

plt.ion()
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 = 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.draw()

print 'FPS: %f' % (100 / (time.time() - tstart))

reference: http://www.mail-archive.com/[email protected]/msg14674.html

The problem with this plot is that is not interactive, the window does not rotate. It seems the computation and/or the rendering blocks the UI

is there a better approach for animated 2D data surface plotting?

$\endgroup$
2

2 Answers 2

4
$\begingroup$

Use the animation module. Here is a nice tutorial.

Tweaking your code a bit,

from mpl_toolkits.mplot3d import axes3d
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

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_wireframe(X, Y, Z, rstride=2, cstride=2)
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_wireframe(X, Y, Z, rstride=2, cstride=2)
    ax.set_zlim(-1,1)
    return wframe,

ani = animation.FuncAnimation(fig, update, 
        frames=xrange(100), 
        fargs=(ax, fig), interval=100)
plt.show()
$\endgroup$
0
$\begingroup$
from mpl_toolkits.mplot3d import axes3d
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

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_wireframe(X, Y, Z, rstride=2, cstride=2)
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_wireframe(X, Y, Z, rstride=2, cstride=2)
    ax.set_zlim(-1,1)
    return wframe,

def xrange(x):
    return iter(range(x))

ani = animation.FuncAnimation(fig, update, frames=xrange(100), 
    fargs=(ax, fig), interval=100)
plt.show()
$\endgroup$
1
  • $\begingroup$ It is a good idea to have at least one sentence that explains your code (or what you had modified in the original code). $\endgroup$
    – Anton Menshov
    Apr 8, 2017 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.