阅读Mayavi的文档" http://docs.enthought.com/mayavi/mayavi/building_applications.html"让我真的很困惑。
我的问题是,如果我只是想要一个允许用户互动的3d图,例如,拖动滑块并更改图的内容,我就 来使用Traits , 对?通过文档,标准程序类似于:
class visual(HasTraits):
scene = ...
view = View(...)
@on_trait_change(...)
def do_something()
...
我不知道什么是特质。我甚至不理解在构造函数之外定义的类中的属性(它是' trait'?)。
回到最初的问题,如果我只想要一个可以改变的3d情节,为什么我不直接这样做?一个工作的例子如下:
import numpy as np
from mayavi import mlab
from matplotlib import pyplot as plt
from matplotlib.widgets import Slider
def slider_changed(val):
s.mlab_source.scalars = np.asarray(x * (val + 1), 'd')
# mayavi 3d plot
x, y = np.mgrid[0:3:1,0:3:1]
s = mlab.surf(x, y, np.asarray(x*0.1, 'd'))
# a matplotlib slider
plt.figure()
ax = plt.subplot(1, 1, 1)
slider = Slider(ax, valmin=0., valmax=1., label='test')
slider.on_changed(slider_changed)
plt.show()
mlab.show()
如果我不关心嵌入应用程序中的3d图,这对我来说似乎是一种更简单的方法吗? 3d绘图的许多属性可通过mlab_source
的属性进行操作。我在这里使用matplotlib滑块作为示例,但它似乎可以是pyqt UI或其他任何东西。
然而,文档说
管道和管道对象的所有不同属性都表示为Traits,即可以在对话框中显示的特殊属性,以及在修改它们时触发回调。特别是这意味着当修改可视化对象时,场景可以自动更新。
这是否意味着如果我想要自动更新的内容,我必须按照上述方式使用Traits?
答案 0 :(得分:2)
理解特征可能是一个良好的开端this article。我们在这里讨论的那些特征是developped by Enthough。值得注意的是,还有其他一些称为特征的对象/概念,它与使用mayavi相关的东西完全无关。
我不必使用Traits,对吧?
您在调用s.mlab_source.scalars = np.asarray(x * (val + 1), 'd')
时使用Traits。 Mayavi仅因为您更改基础数据而更新情节的事实是使用Traits的结果。
Mayavi只使用这些特征,而不是通常的对象。所以一旦你使用mayavi,你就不可避免地会使用特征。
这是否意味着如果我想要自动更新的东西,我必须按照上面描述的方式使用Traits?
不,你自己给了反例。您不必子类HasTraits
来更新绘图。您可以使用您能想到的任何其他解决方案。但是,一旦你想将mayavi场景嵌入到GUI中,按照文档说明的方式进行操作可能是个好主意。
另外,子类化HasTraits
实际上是一种非常简洁的方式来轻松获得交互式图形。所以问题的例子看起来像
import numpy as np
from mayavi import mlab
from traits.api import HasTraits, Range, Instance,on_trait_change
from traitsui.api import View, Item, Group
from mayavi.core.ui.api import MayaviScene, SceneEditor, MlabSceneModel
x, y = np.mgrid[0:3:1,0:3:1]
class MyModel(HasTraits):
slider = Range(-5., 5., 0.5, )
scene = Instance(MlabSceneModel, ())
def __init__(self):
HasTraits.__init__(self)
self.s = mlab.surf(x, y, np.asarray(x*1.5, 'd'), figure=self.scene.mayavi_scene)
@on_trait_change('slider')
def slider_changed(self):
self.s.mlab_source.scalars = np.asarray(x * (self.slider + 1), 'd')
view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene)),
Group("slider"))
my_model = MyModel()
my_model.configure_traits()
这里要注意的好处是你实际上没有定义一个显式的回调(即没有on_slider_change
或类似的)。