如何避免Mayavi管道污染?
How to avoid Mayavi pipeline pollution?
下面是一些最小的代码,它充分展示了我所谓的"pipeline pollution"。每次按下 'Draw' 按钮时,MayaviScene 编辑器(通过图中左上角的按钮访问)将更新该图,但也会创建一个新场景的 "shell" 在管道中徘徊(如见附图)。
我担心在我更复杂的项目中,这种堆积会产生不利影响。
有人可以指导我如何最好地设置这个 Mayavi 场景,以便在没有过多积累的情况下简单地更新吗?网上资料看了一大堆,还是不懂开发者的逻辑。
import sys, os
import numpy as np
from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'
from traits.api import HasTraits,Instance,on_trait_change
from traitsui.api import View,Item
from mayavi import mlab
from mayavi.core.ui.api import MayaviScene, MlabSceneModel, SceneEditor
class Mayavi_Scene(HasTraits):
scene = Instance(MlabSceneModel, ())
def update_scene(self):
Mayavi_Scene.fig1 = mlab.figure(1, bgcolor=(.5,.5,.5))
self.scene.mlab.clf(figure=Mayavi_Scene.fig1)
splot = mlab.points3d(P1.x, P1.y, P1.z,
scale_factor=0.05, figure=Mayavi_Scene.fig1)
view = View(Item('scene', editor = SceneEditor(scene_class=MayaviScene),
height=300, width=300, show_label=False),
resizable=True,
)
class P1(QtGui.QWidget):
# data starts out empty, wait for user input (below, via 'draw()'):
x = []
y = []
z = []
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QtGui.QGridLayout(self)
layout.setContentsMargins(20,20,20,20)
layout.setSpacing(10)
self.viz1 = Mayavi_Scene()
self.ui1 = self.viz1.edit_traits(parent=self, kind='subpanel').control
layout.addWidget(self.ui1, 0, 0, 1, 1)
def draw(): #a sample user input, could have been a custom data file, etc.
P1.x = np.random.random((100,))
P1.y = np.random.random((100,))
P1.z = np.random.random((100,))
Mayavi_Scene().update_scene()
#repeated presses pollute MayaviScene pipeline
# button to draw data:
self.btn1 = QtGui.QPushButton('Draw',self)
self.connect(self.btn1, QtCore.SIGNAL('clicked()'), draw)
layout.addWidget(self.btn1, 1, 0, 1, 1)
self.btn1.show()
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.window = P1(self)
self.setCentralWidget(self.window)
self.show()
if __name__ == '__main__':
app = QtGui.QApplication.instance()
w = MainWindow()
sys.exit(app.exec_())
原因可能是 draw
内部函数中包含 Mayavi_Scene().update_scene()
的行。每次调用 draw
时,都会创建一个新的 Mayavi_Scene
。以下 P1
class 将 draw
定义为直接访问 self.viz1
的方法。我还将对 draw
的引用替换为对 self.draw
的引用
class P1(QtGui.QWidget):
# data starts out empty, wait for user input (below, via 'draw()'):
x = []
y = []
z = []
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QtGui.QGridLayout(self)
layout.setContentsMargins(20,20,20,20)
layout.setSpacing(10)
self.viz1 = Mayavi_Scene()
self.ui1 = self.viz1.edit_traits(parent=self, kind='subpanel').control
layout.addWidget(self.ui1, 0, 0, 1, 1)
# button to draw data:
self.btn1 = QtGui.QPushButton('Draw',self)
# Connect the widget's draw method and the button
self.connect(self.btn1, QtCore.SIGNAL('clicked()'), self.draw)
layout.addWidget(self.btn1, 1, 0, 1, 1)
self.btn1.show()
def draw(self): #a sample user input, could have been a custom data file, etc.
P1.x = np.random.random((100,))
P1.y = np.random.random((100,))
P1.z = np.random.random((100,))
# Update the current scene without creating a new one.
self.viz1.update_scene()
下面是一些最小的代码,它充分展示了我所谓的"pipeline pollution"。每次按下 'Draw' 按钮时,MayaviScene 编辑器(通过图中左上角的按钮访问)将更新该图,但也会创建一个新场景的 "shell" 在管道中徘徊(如见附图)。
我担心在我更复杂的项目中,这种堆积会产生不利影响。
有人可以指导我如何最好地设置这个 Mayavi 场景,以便在没有过多积累的情况下简单地更新吗?网上资料看了一大堆,还是不懂开发者的逻辑。
import sys, os
import numpy as np
from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'
from traits.api import HasTraits,Instance,on_trait_change
from traitsui.api import View,Item
from mayavi import mlab
from mayavi.core.ui.api import MayaviScene, MlabSceneModel, SceneEditor
class Mayavi_Scene(HasTraits):
scene = Instance(MlabSceneModel, ())
def update_scene(self):
Mayavi_Scene.fig1 = mlab.figure(1, bgcolor=(.5,.5,.5))
self.scene.mlab.clf(figure=Mayavi_Scene.fig1)
splot = mlab.points3d(P1.x, P1.y, P1.z,
scale_factor=0.05, figure=Mayavi_Scene.fig1)
view = View(Item('scene', editor = SceneEditor(scene_class=MayaviScene),
height=300, width=300, show_label=False),
resizable=True,
)
class P1(QtGui.QWidget):
# data starts out empty, wait for user input (below, via 'draw()'):
x = []
y = []
z = []
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QtGui.QGridLayout(self)
layout.setContentsMargins(20,20,20,20)
layout.setSpacing(10)
self.viz1 = Mayavi_Scene()
self.ui1 = self.viz1.edit_traits(parent=self, kind='subpanel').control
layout.addWidget(self.ui1, 0, 0, 1, 1)
def draw(): #a sample user input, could have been a custom data file, etc.
P1.x = np.random.random((100,))
P1.y = np.random.random((100,))
P1.z = np.random.random((100,))
Mayavi_Scene().update_scene()
#repeated presses pollute MayaviScene pipeline
# button to draw data:
self.btn1 = QtGui.QPushButton('Draw',self)
self.connect(self.btn1, QtCore.SIGNAL('clicked()'), draw)
layout.addWidget(self.btn1, 1, 0, 1, 1)
self.btn1.show()
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.window = P1(self)
self.setCentralWidget(self.window)
self.show()
if __name__ == '__main__':
app = QtGui.QApplication.instance()
w = MainWindow()
sys.exit(app.exec_())
原因可能是 draw
内部函数中包含 Mayavi_Scene().update_scene()
的行。每次调用 draw
时,都会创建一个新的 Mayavi_Scene
。以下 P1
class 将 draw
定义为直接访问 self.viz1
的方法。我还将对 draw
的引用替换为对 self.draw
class P1(QtGui.QWidget):
# data starts out empty, wait for user input (below, via 'draw()'):
x = []
y = []
z = []
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QtGui.QGridLayout(self)
layout.setContentsMargins(20,20,20,20)
layout.setSpacing(10)
self.viz1 = Mayavi_Scene()
self.ui1 = self.viz1.edit_traits(parent=self, kind='subpanel').control
layout.addWidget(self.ui1, 0, 0, 1, 1)
# button to draw data:
self.btn1 = QtGui.QPushButton('Draw',self)
# Connect the widget's draw method and the button
self.connect(self.btn1, QtCore.SIGNAL('clicked()'), self.draw)
layout.addWidget(self.btn1, 1, 0, 1, 1)
self.btn1.show()
def draw(self): #a sample user input, could have been a custom data file, etc.
P1.x = np.random.random((100,))
P1.y = np.random.random((100,))
P1.z = np.random.random((100,))
# Update the current scene without creating a new one.
self.viz1.update_scene()