Приветствую, хабравчане!
Сегодня хочу вам рассказать о том, что такое Mayavi и с чемего запивают его едят.
Mayavi — это кроссплатформенное приложение для визуализации научных данных (и не только). Распространяется по лицензии BSD, что позволяет использовать его в коммерческих приложениях.
Что умеет?
Работать с ним можно тремя способами:
1) Работать непосредственно в интерфейсе Mayavi.
2) Подгружать/передавать в Mayavi уже готовые данные.
3) Написать питоновский скрипт, в котором можно задать для Mayavi все желаемые возможности.
После запуска stand-alone версии получаем такое вот милое окошко:
Экран поделен на 4 части:
Поясню для чего нужен терминал:
Создадим какой-нибудь объект и выберем его в списке объектов. Выделим и, не отпуская левой кнопки мыши, перетащим в окошко терминала. Получим что-то вроде
Теперь напишем:
и тогда появится окно со всеми параметрами объекта. Это очень полезная вещь, которая может помочь в изучении и создании собственных скриптов. Некоторые свойства объектов я узнал именно этим способом, не найдя в документации. В этом окне правило Drag'N'Drop работает аналогично.
В документации к Mayavi есть достаточно много (примеров), которые в общем поясняют что и как нужно делать.
Попробую описать те грабли, на которые я наступил. По большей части они будут касаться встраивания фрэйма Mayavi в виджет PyQt (ну или PySide, о котором уже писал.
Запускаем и получаем вот такое окошко:
Жмякаем кнопку и получаем цветной кубик:
Если захочется увидеть что-то более научное, то можете взглянуть на это:
Ну а еще можно создать что-то футуристичное (внутри одного параллелепипеда с включенными внутренними гранями):
На этом завершаю свой топик. Если хотите увидеть что-то еще, то жду комментариев.
P.S. Чуть позже напишу топик про Chaco. Я надеюсь вам так же интересно прочитать о нем?
Сегодня хочу вам рассказать о том, что такое Mayavi и с чем
Mayavi — это кроссплатформенное приложение для визуализации научных данных (и не только). Распространяется по лицензии BSD, что позволяет использовать его в коммерческих приложениях.
Что умеет?
- Строить 2D и 3D модели на основе скалярных/векторных данных
- Открывать файлы VTK, PLOT3D
- Сохранять результаты рендера в различных графических форматах
- Может даже рендерить результаты MRI(Магнитно-резонансная томография)
Работать с ним можно тремя способами:
1) Работать непосредственно в интерфейсе Mayavi.
2) Подгружать/передавать в Mayavi уже готовые данные.
3) Написать питоновский скрипт, в котором можно задать для Mayavi все желаемые возможности.
После запуска stand-alone версии получаем такое вот милое окошко:
Экран поделен на 4 части:
- Левая верхняя часть хранит объекты
- В левой нижней части изменяются свойства объектов
- В правой верхней происходит рендер
- В правом нижнем углу находится терминал
Поясню для чего нужен терминал:
Создадим какой-нибудь объект и выберем его в списке объектов. Выделим и, не отпуская левой кнопки мыши, перетащим в окошко терминала. Получим что-то вроде
<enthought.mayavi.modules.surface.Surface object at 0x0DADE5D0>
Теперь напишем:
explore(_)
и тогда появится окно со всеми параметрами объекта. Это очень полезная вещь, которая может помочь в изучении и создании собственных скриптов. Некоторые свойства объектов я узнал именно этим способом, не найдя в документации. В этом окне правило Drag'N'Drop работает аналогично.
В документации к Mayavi есть достаточно много (примеров), которые в общем поясняют что и как нужно делать.
Попробую описать те грабли, на которые я наступил. По большей части они будут касаться встраивания фрэйма Mayavi в виджет PyQt (ну или PySide, о котором уже писал.
- Не читайте документацию из pdf файлов. Правда, не читайте. Бесполезная трата времени.
- Не заменяйте по привычке конструкторы классов. Создавайте какие-нибудь методы, в которые будут передаваться переменные/объекты, которые затем использоваться для рендера в функциях update_plot().
- Постарайтесь точно определить то, что вы хотите увидеть. Классы TVTK могут не поддерживать тех функций, которые есть у классов mlab(например Volume).
- При работе с numpy-массивами, приводите их к типу float32, т.к. по умолчанию на 64 битной системе создается float64-массив, с которым Mayavi работать не будет.
- Приведу один пример построения обычного кубика со встраиванием его в виджет PyQT.
- # Для встраивания в виджет PyQt4 нужно установить переменную ETS_TOOLKIT в значение qt4.
- import os
- os.environ['ETS_TOOLKIT'] = 'qt4'
- from PySide import QtGui, QtCore
- from enthought.mayavi import mlab
- from enthought.tvtk.api import tvtk
- from enthought.tvtk.pyface.api import Scene
- from numpy import arange, nonzero, float32, min, max, median, copy, random, shape
- from numpy.core.numeric import ravel
- from enthought.traits.api import HasTraits, Instance, on_trait_change, \
- Int, Dict
- from enthought.traits.ui.api import View, Item
- from enthought.mayavi.core.ui.api import MayaviScene, MlabSceneModel, \
- SceneEditor
- #The actual visualization
- class Visualization(HasTraits):
- scene = Instance(MlabSceneModel, ())
- view = View(Item('scene',
- editor=SceneEditor(scene_class=MayaviScene),
- # Вместо MayaviScene можно написать просто Scene
- # и тогда получим чистое окошко без тулбара.
- height=250,
- width=300,
- show_label=False),
- resizable=True
- )
- needUpdate = None
- def takePlotParametres(self, grid):
- self.grid = grid
- # Метод clf() очищает текущую сцену. Его НЕЛЬЗЯ вызывать в методе update_plot()
- self.scene.mlab.clf()
- self.needUpdate = True
- self.update_plot()
- @on_trait_change('scene.activated')
- def update_plot(self):
- # Этот метод вызывается для отрисовки.
- # Все, что нужно отрисовать, записывается именно сюда и больше никуда
- # Пока нет никаких данных, отрисуем стандартную модель
- if not self.needUpdate:
- self.scene.mlab.test_points3d()
- else:
- # Сюда пишем все свои рисовашки
- # Все, что отрисовывается через mlab, нужно вызывать
- # как self.scene.mlab.* , иначе окошко Mayavi выходит из под контроля
- # и начинает рисовать все в отдельном окошке.
- # opacity сильно влияет на производительность отрисовки!
- surf = self.scene.mlab.pipeline.surface(self.grid, opacity=1)
- # Можно так же отображать и внутреннюю сетку, раскомментировав строки
- #edges = mlab.pipeline.extract_edges(surf)
- #edgesSurf = mlab.pipeline.surface(edges)
- #edgesSurf.actor.property.interpolation = 'flat'
- # Уберем интерполяцию окраски поверхности куба. Пусть каждую ячейку будет видно отчетливо.
- surf.actor.property.interpolation = 'flat'
- self.scene.mlab.orientation_axes()
- self.scene.background = (0, 0, 0)
- self.scene.mlab.colorbar(orientation='vertical')
- ################################################################################
- # Виджет, в который встроим сцену. Используем его как обычный виджет PyQt.
- class MayaviQWidget(QtGui.QWidget):
- def __init__(self, parent=None):
- QtGui.QWidget.__init__(self, parent)
- layout = QtGui.QVBoxLayout(self)
- layout.setMargin(0)
- layout.setSpacing(0)
- self.visualization = Visualization()
- # В идеале именно тут можно вызывать метод takePlotParametres с начальными данными, но это не обязательно
- # self.visualization.takePlotParametres()
- # Метод edit_traits генерирует окно, в котором строится сцена.
- # Это окошко нужно сделать Qt'шным, для чего вызываем метод .control
- self.ui = self.visualization.edit_traits(parent=self,
- kind='subpanel').control
- layout.addWidget(self.ui)
- self.ui.setParent(self)
- def create_cube(self):
- grid = self.createGrid()
- self.visualization.takePlotParametres(grid)
- def createGrid(self):
- x, y, z = (10, 10, 10)
- # Создадим сетку для нашего куба
- grid = tvtk.RectilinearGrid()
- # Важно приводить данные к float32, т.к. на 64-битной ОС numpy по умолчанию создает float64,
- # а Mayavi работать с ним не умеет.
- # Создадим рандомные данные
- scalars = float32(random.random((x*y*z)))
- # scalars - это значение, которое будет храниться в каждой ячейке нашего кубика.
- # Именно по этому значению определяется окраска поверхности ячеек
- grid.point_data.scalars = scalars
- grid.point_data.scalars.name = 'scalars'
- grid.dimensions = (x, y, z)
- grid.x_coordinates = float32(arange(x))
- grid.y_coordinates = float32(arange(y))
- grid.z_coordinates = float32(arange(z))
- return grid
- if __name__ == "__main__":
- # Важно не создавать новое приложение, а использовать то,
- # которое Mayavi создает автоматически, иначе вы собьете все сигналы/слоты Traits,
- # а нам это как раз не нужно.
- # Чтобы получить ссылку, вызываем метод instance().
- # Не напишите по привычке QtGui.QApplication(sys.argv).instance(),
- # я уже наступал на эти грабли.
- app = QtGui.QApplication.instance()
- container = QtGui.QWidget()
- container.setWindowTitle("Hello Habrahabr!")
- layout = QtGui.QVBoxLayout(container)
- mayavi_widget = MayaviQWidget()
- button = QtGui.QPushButton('Create cube')
- button.clicked.connect(mayavi_widget.create_cube)
- layout.addWidget(mayavi_widget)
- layout.addWidget(button)
- container.show()
- app.exec_()
Запускаем и получаем вот такое окошко:
Жмякаем кнопку и получаем цветной кубик:
Если захочется увидеть что-то более научное, то можете взглянуть на это:
Ну а еще можно создать что-то футуристичное (внутри одного параллелепипеда с включенными внутренними гранями):
На этом завершаю свой топик. Если хотите увидеть что-то еще, то жду комментариев.
P.S. Чуть позже напишу топик про Chaco. Я надеюсь вам так же интересно прочитать о нем?