0

I have a text file that contains data for ax.plot_surface.

I would like to plot it in real time, that is to see the figure draw in real time. My current solution does more or less the job by dealing with indexes.

The problem is it is extremely slow as for each frame I have to clear the figure.

I am new with Matplotlib, how could I accelerate the process? Also, in the final code I will directly save the figure instead of plotting it.

My current code:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm

fig = plt.figure()
X, Y, Z = axes3d.get_test_data(0.05)

cpt = 0
for i in xrange(0, X.shape[0], 2):
  for j in xrange(0, X.shape[1]):
    ax = fig.gca(projection='3d')

    if i > 1:
      # Plot continuous surface from the beginning
      ax.plot_surface(X[0:i-2, :], Y[0:i-2, :], Z[0:i-2, :], rstride=8, cstride=8, alpha=0.3)
      # Plot the current column
      ax.plot_surface(X[i-2:i, 0:j], Y[i-2:i, 0:j], Z[i-2:i, 0:j], rstride=8, cstride=8, alpha=0.3)
    else:
      ax.plot_surface(X[0:i, 0:j], Y[0:i, 0:j], Z[0:i, 0:j], rstride=8, cstride=8, alpha=0.3)

    ax.set_xlabel('X')
    ax.set_xlim(-40, 40)
    ax.set_ylabel('Y')
    ax.set_ylim(-40, 40)
    ax.set_zlabel('Z')
    ax.set_zlim(-100, 100)

    plt.pause(0.001)

    # Save in file directly
    #filename = 'TMP/%04d.png' % cpt
    #plt.savefig(filename, bbox_inches='tight')
    cpt += 1

    plt.gcf().clear()

Edit:

Based on @River comment, the following code try to draw only the current "tile". Seems a little bit faster but the result is not as nice as the whole surface was redrew entirely before.

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm

fig = plt.figure()
X, Y, Z = axes3d.get_test_data(0.05)

ax = fig.gca(projection='3d')

ax.set_xlabel('X')
ax.set_xlim(-40, 40)
ax.set_ylabel('Y')
ax.set_ylim(-40, 40)
ax.set_zlabel('Z')
ax.set_zlim(-100, 100)

cpt = 0
for i in xrange(0, X.shape[0], 2):
  for j in xrange(0, X.shape[1], 2):

    if i > 1:
      # Plot the current column
      ax.plot_surface(X[i-2:i, j-2:j], Y[i-2:i, j-2:j], Z[i-2:i, j-2:j], rstride=8, cstride=8, alpha=0.3)

    plt.pause(0.001)

    # Save in file directly
    #filename = 'TMP/%04d.png' % cpt
    #plt.savefig(filename, bbox_inches='tight')
    cpt += 1

Note:

I realize also I have to output the same number of figures than my data (I want to make a video with on the left side the result and on the right side the graph). I think that it means that even if we can increment by 2 (we draw directly a "tile"), I have to increment by 1 which is inefficient but necessary in my case I think.

Catree
  • 2,477
  • 1
  • 17
  • 24
  • It seems that you have to create a manual update function to deal with this if you don't want to clear it every time. [See here](http://stackoverflow.com/questions/4098131/how-to-update-a-plot-in-matplotlib) – River Jun 16 '16 at 12:24
  • Look at matplotlib animation. You will want to create the plot only once as there is a lot of overhead in creation. It will create a Poly3DCollection object.Then you just want to update the data. I think you should be able to do that with set_verts. http://matplotlib.org/mpl_toolkits/mplot3d/api.html?highlight=plot_surface#mpl_toolkits.mplot3d.art3d.Poly3DCollection – justengel Jun 16 '16 at 13:45

0 Answers0