Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate 3d plot_surface in matplotlib

I have created a 3D plot surface from a file and I'm trying to animate the plot. I have read the examples in the matplotlib webpage and other examples in SO, and notice that I need to create an update function to loop through the values in the file and then create a matplotlib.animation object but I don't understand how to do it.

I would appreciate very much if someone could explain me the syntax of the update function and how to use it in the matplotlib.animation object.

My data is a multidimensional array with 498 lines and for each line i have an array with 64x128 values. Data is organized in the following way:

Data is a time series from a force plate and each one of the 500 lines is a frame, which means that this trial lasts 10 seconds. For each frame I have another array with 64x128 values.

This is my code until now:

from mpl_toolkits.mplot3d import *
import matplotlib.pyplot as plt
import numpy as np
from random import random, seed
from matplotlib import cm
from mpl_toolkits.mplot3d import axes3d
import matplotlib.animation as animation

source_path = "c:\\Projecto\\"
destination_path = "c:\\Projecto\\EntirePlate\\"
#fid = np.loadtxt(source_path + "rolloff_xls.txt",dtype=str)

fid_MP = open(source_path + "101mp - Entire plate roll off.xls","Ur")
lines_MP = fid_MP.readlines()
fid_MP.close()

values_MP = []

for i in lines_MP:
      if i[0].isdigit():
          values_MP.append(i)

values = np.loadtxt(values_MP,dtype=float)

new_values_MP =[]

for i in range(0,(len(values_MP)/64)):
    for j in range(0,64):
        new_values_MP.append([[i],[j],values[j]])

new_values_MP = np.asarray(new_values_MP)

fig = plt.figure()
ax = fig.gca(projection='3d')               # to work in 3d
plt.hold(True)

x_surf = np.arange(0,128)                # generate a mesh
y_surf = np.arange(0,64)
x_surf, y_surf = np.meshgrid(x_surf, y_surf)
z_surf = []

for i in range(0,64):
     # print(new_values[i])
     z_surf.append(np.asarray(new_values_MP[i][2])) # ex. function, which depends on x and y

z_surf = np.asarray(z_surf).reshape([64,128])

ax.plot_surface(x_surf, y_surf, z_surf, rstride=2, cstride=2 ,cmap=cm.jet)    # plot a 3d surface plot

ax.set_xlabel('Medio Lateral - Axis')
ax.set_ylabel('Anterior Posterior - Axis')
ax.set_zlabel('Pressure (P)')

def update(x_values, y_values, z_values):
     for i in range(0,len(values_MP)/64):
         x_surf = x_values
         y_surf = y_values
         z_surf.set_data(new_values_MP[i,2])
     return z_surf

ani = animation.FuncAnimation(fig, update, frames=xrange(len(values_MP)/64),
                               interval=50, blit=False)
plt.show()
 
like image 447
TMoover Avatar asked Jun 25 '13 14:06

TMoover


People also ask

Can Matplotlib plot 3D images?

Among these, Matplotlib is the most popular choice for data visualization. While initially developed for plotting 2-D charts like histograms, bar charts, scatter plots, line plots, etc., Matplotlib has extended its capabilities to offer 3D plotting modules as well.


1 Answers

This is possibly not the optimal way, but I found the documentation/examples not sufficient too.

What I resorted to is the following solution: use animation.FuncAnimation to call a function. In that function clear and redraw, like so:

from __future__ import division
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
import numpy as np

plot_args = {'rstride': 1, 'cstride': 1, 'cmap':
             cm.bwr, 'linewidth': 0.01, 'antialiased': True, 'color': 'w',
             'shade': True}

soln = np.zeros((size, size))
midpoint = size // 2
soln[midpoint, midpoint] = 1

#first frame
X = range(size)
Y = range(size)
X, Y = np.meshgrid(X, Y)
plot = ax.plot_surface(X, Y, soln, **plot_args)
pam_ani = animation.FuncAnimation(fig, data_gen, fargs=(soln, plot),
                              interval=30, blit=False)

def data_gen(framenumber, soln, plot):
    #change soln variable for the next frame
    ...
    ax.clear()
    plot = ax.plot_surface(X, Y, soln, **plot_args)
    return plot,
like image 152
Tom Artiom Fiodorov Avatar answered Oct 07 '22 09:10

Tom Artiom Fiodorov