matplotlib 连续3D绘图(i.即数字更新)

rfbsl7qr  于 2023-05-01  发布在  其他
关注(0)|答案(3)|浏览(140)

我有一个模拟计算表面数据的每次迭代的模拟。我想连续地将这些数据绘制为同一窗口的曲面图(在每次迭代中更新图),以便查看它如何演变并检查算法。
我的想法是创建一个类,它将初始化窗口/绘图,然后从模拟循环内部重新绘制到该窗口。下面是我提出的类:

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)

我对这段代码的问题是,代码停在'plt。show()',并且只有在我关闭绘图窗口时才继续。我也不确定自己的电话。ax.plot_surface(...)’和’plt.draw()'会按照我的意愿更新图形。
这门课是正确的方向吗?
如果是:需要进行哪些修改?
如果没有:有人能给予我建议如何实现我想要的吗?
我知道这个问题对其他人来说可能微不足道,但我(老实说)昨天花了一整天在谷歌上尝试,我不知所措。..
任何帮助都将不胜感激,这样我就可以回到我的实际工作。
坦克在前面。
作为参考:
我还找到了下面的代码,它做了我想要的,但它是2D的,所以它不能直接帮助我:

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)
5lhxktic

5lhxktic1#

如果是动画(交互式)绘图,则不需要plt.show()。您还需要将interactive设置为True,而不是False,这与在2d示例中调用ion()相同。此外,如果不想全部查看,则需要remove()以前帧的曲面图。
否则你们就差一点了。
这对我很有效:

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))
h7appiyu

h7appiyu2#

我也遇到过类似的问题,这对我很有效:

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()

对你来说,我会想象解决方案类似于the top answer,只是用plt.pause()替换time.sleep(),这样就可以在睡觉前完成图形的绘制。

pkbketx9

pkbketx93#

我很感激保罗的回答,虽然我还没有尝试过。
与此同时,我发现了另一种解决方案,它可以使用MayaVI与OpenGL一起工作和渲染,这是可以的,因为我只需要实时快速的视觉反馈。但是,我必须在Ubuntu下安装以下软件包:python-enthoughtbase和mayavi 2
代码如下:

import numpy as np
import time
from enthought.mayavi import mlab
from enthought.tvtk.tools import visual

    class plot3dClass( object ):

        def __init__( self, systemSideLength, lowerCutoffLength ):
            self.systemSideLength = systemSideLength
            self.lowerCutoffLength = lowerCutoffLength

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

            matrixSize = int( round( self.systemSideLength / self.lowerCutoffLength ) )
            heightR = np.zeros( ( matrixSize, matrixSize ) )

            fig = mlab.figure(size=(500,500))
            visual.set_viewer(fig)
            self.surf = mlab.surf( X, Y, heightR, warp_scale = 1e1 ) # NOTE: the warp_scale factor is relative to the scale of the x- and y-axes
            box_extent = ( 0,rangeMax, 0,rangeMax, -1e-7,1e-7 ) # NOTE: the extent options refers to the size and position in the 3D space relative to the origin

            mlab.outline(self.surf, color=(0.7, .7, .7), extent = box_extent )

        def drawNow( self, heightR ):
            self.surf.mlab_source.scalars = heightR
            time.sleep(0.033)

这个类并不是我想要的,我有两个直接的问题:
1.经过短暂的意志,窗口被Ubuntu变灰,因为(我想)Ubuntu认为应用程序没有响应。也许是Ubuntu的问题,但很烦人。
1.我一直在努力找出如何能够在动画制作的同时用鼠标旋转情节。
我会尝试在另一个线程中得到答案。

**EDIT:**Ok.我刚刚尝试了保罗建议的代码,它也适用于我。然而,尝试它,我已经意识到MatPlotLib可能不是实时制作动画的最佳选择。至少对我来说它是极其缓慢的(也许只在3D?).

所以最后我将坚持使用上面提到的MayaVI实现,除了上面提到的两点,它工作得很好。

**编辑:**如果你使用MatPlotLib解决方案,我发现你可以将matplotlib.interactive(True)行放在plotting类的声明中。这样您就可以只在绘图类中定义MatPlotLib。

相关问题