Below is some minimal code that fully demonstrates what I call "pipeline pollution". Each time you press the 'Draw' button, the MayaviScene editor (accessed via the top-left button on the figure) will update the figure, but also create a new scene's "shell" that lingers in the pipeline (as seen in the attached image).
I'm worried that in my more complex project, this pileup will have adverse effects.
Can someone please guide me on how to best set up this Mayavi scene to simply be updated without excess accumulation? I've read through tons of online materials, but still don't understand the developer's logic.
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_())
The cause is likely the line containing Mayavi_Scene().update_scene()
in the draw
internal function. Every time draw
is called, it creates a new Mayavi_Scene
. The following P1
class instead defines draw
as a method that accesses self.viz1
directly. I've also replaced the reference to draw
with a reference to 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()