Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continuous 3D plotting (i.e. figure update) using python-matplotlib?

I have a simulation which calculates surface data for each iteration of the simulation. I would like to continuously plot that data as a surface plot to the same window (updating the plot in each iteration) in order to see how it evolves and to check the algorithm.

My Idea was to create a class that would initialize the window/plot and then redraw to that window from inside the simulation loop. Here is the class I came up with:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FixedLocator, FormatStrFormatter
import matplotlib
matplotlib.interactive( False )

class plot3dClass( object ):

    def __init__( self, systemSideLength, lowerCutoffLength ):
        self.systemSideLength = systemSideLength
        self.lowerCutoffLength = lowerCutoffLength
        self.fig = plt.figure()
        self.ax = self.fig.add_subplot( 111, projection='3d' )
        self.ax.set_zlim3d( -10e-9, 10e9 )

        X = np.arange( 0, self.systemSideLength, self.lowerCutoffLength )
        Y = X
        self.X, self.Y = np.meshgrid(X, Y)

        self.ax.w_zaxis.set_major_locator( LinearLocator( 10 ) )
        self.ax.w_zaxis.set_major_formatter( FormatStrFormatter( '%.03f' ) )

        heightR = np.zeros( self.X.shape )
        self.surf = self.ax.plot_surface( self.X, self.Y, heightR, rstride=1, cstride=1, cmap=cm.jet, linewidth=0, antialiased=False )
        #~ self.fig.colorbar( self.surf, shrink=0.5, aspect=5 )

        plt.show()


    def drawNow( self, heightR ):

        self.surf = self.ax.plot_surface( self.X, self.Y, heightR, rstride=1, cstride=1, cmap=cm.jet, linewidth=0, antialiased=False )
        plt.draw()                      # redraw the canvas

        time.sleep(1)

The problem I have with this code, is that the code stops at the 'plt.show()' and only continues, when I close the plot-window. Also I am not sure if the calls of 'self.ax.plot_surface( ... )' and 'plt.draw()' would update the figure as I would like it.

So is this class the right direction?

If yes: What modifications are needed?

If not: Could somebody please give me advice how to achieve what I want?

I realize that this problem might seem trivial to others, but I (honestly) did spend the whole day yesterday on Google and trying and I'm at a loss...

Any help would greatly appreciated, so that I can get back to my actual work.

Tanks alot in advance.

As a reference:

I also found the following code which does, what I want, but it is in 2D, so it does not help me directly:

from pylab import *
import time

ion()

tstart = time.time()               # for profiling
x = arange(0,2*pi,0.01)            # x-array
line, = plot(x,sin(x))

for i in arange(1,200):
    line.set_ydata(sin(x+i/10.0))  # update the data
    draw()                         # redraw the canvas

print 'FPS:' , 200/(time.time()-tstart)
like image 415
Mike Avatar asked Mar 03 '11 10:03

Mike


People also ask

How do I update a figure in matplotlib?

Using matplotlib. pyplot. draw(), It is used to update a figure that has been changed. It will redraw the current figure.

Can matplotlib be used for 3D plotting?

In order to plot 3D figures use matplotlib, we need to import the mplot3d toolkit, which adds the simple 3D plotting capabilities to matplotlib. Once we imported the mplot3d toolkit, we could create 3D axes and add data to the axes. Let's first create a 3D axes. The ax = plt.

How do you plot a continuous graph in Python?

Plotting a continuous function plot with Seaborn # using seaborn import seaborn as sns import numpy as np # create data x = np. linspace(10, 100,10) y=np. power(x,3) # draw the graph sns. set_style('dark') fig,ax= plt.


2 Answers

You do not need to plt.show() if it is an animated (interactive) plot. You also want interactive set to True, not False which is the same as calling ion() in your 2d example. Also, you need to remove() the surface plots from previous frames if you do not want to see them all.

Otherwise you were pretty close.

This works for me:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FixedLocator, FormatStrFormatter
import matplotlib, time

class plot3dClass( object ):

    def __init__( self, systemSideLength, lowerCutoffLength ):
        self.systemSideLength = systemSideLength
        self.lowerCutoffLength = lowerCutoffLength
        self.fig = plt.figure()
        self.ax = self.fig.add_subplot( 111, projection='3d' )
        self.ax.set_zlim3d( -10e-9, 10e9 )

        rng = np.arange( 0, self.systemSideLength, self.lowerCutoffLength )
        self.X, self.Y = np.meshgrid(rng,rng)

        self.ax.w_zaxis.set_major_locator( LinearLocator( 10 ) )
        self.ax.w_zaxis.set_major_formatter( FormatStrFormatter( '%.03f' ) )

        heightR = np.zeros( self.X.shape )
        self.surf = self.ax.plot_surface( 
            self.X, self.Y, heightR, rstride=1, cstride=1, 
            cmap=cm.jet, linewidth=0, antialiased=False )
        # plt.draw() maybe you want to see this frame?

    def drawNow( self, heightR ):
        self.surf.remove()
        self.surf = self.ax.plot_surface( 
            self.X, self.Y, heightR, rstride=1, cstride=1, 
            cmap=cm.jet, linewidth=0, antialiased=False )
        plt.draw()                      # redraw the canvas
        time.sleep(1)

matplotlib.interactive(True)

p = plot3dClass(5,1)
for i in range(2):
    p.drawNow(np.random.random(p.X.shape))
like image 80
Paul Avatar answered Nov 05 '22 23:11

Paul


I had a similar problem and this worked for me:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

for k in xrange(0,X_range):
    ax.plot(x_input, y_input, z_input)
    plt.draw()
    plt.pause(0.02)
    ax.cla()

For you, I'd imagine the solution be something similar to the top answer except replacing time.sleep() with plt.pause(), which would finish the drawing the figure before sleeping.

like image 4
jsb Avatar answered Nov 05 '22 23:11

jsb