您当前的位置:首页 > 计算机 > 编程开发 > Python

Python Vispy库:高性能科学可视化工具

时间:08-08来源:作者:点击数:

Vispy是一个用于科学可视化的高性能Python库,特别适用于需要实时交互和大规模数据处理的应用。它基于OpenGL构建,提供了简洁的API,方便开发者创建复杂的可视化应用。Vispy支持2D和3D绘图,能够处理从简单图形到高级图形的大量任务。本文将详细介绍Vispy库的安装、主要功能、基本操作、高级功能及其实践应用,并提供丰富的示例代码。

安装

Vispy可以通过pip进行安装。确保Python环境已激活,然后在终端或命令提示符中运行以下命令:

pip install vispy

Vispy依赖于OpenGL,因此需要确保你的系统已安装OpenGL。

如果你使用的是Linux或macOS,可以通过包管理器安装:

# macOS
brew install --cask xquartz

# Ubuntu
sudo apt-get install libgl1-mesa-glx

对于Windows用户,可以从OpenGL官网下载并安装。

主要功能

  1. 2D和3D绘图:支持创建2D和3D图形。
  2. 实时交互:支持鼠标、键盘等交互操作。
  3. 高性能渲染:基于OpenGL,能够高效处理大规模数据。
  4. 丰富的图形元素:支持点、线、面、体等多种图形元素。
  5. 集成多种后端:支持PyQt、PySide、GLFW等多种图形后端。

基本操作

创建简单的2D绘图

以下示例展示了如何使用Vispy创建一个简单的2D绘图:

import vispy.plot as vp

# 创建一个2D绘图
fig = vp.Fig(size=(800, 600), show=False)
scatter = fig[0, 0].plot((0, 1, 2), (0, 1, 0), symbol='o', width=0)

fig.show(run=True)
创建简单的3D绘图

以下示例展示了如何使用Vispy创建一个简单的3D绘图:

import numpy as np
from vispy import scene

# 创建一个3D绘图
canvas = scene.SceneCanvas(keys='interactive', show=True)
view = canvas.central_widget.add_view()

# 生成随机3D数据
pos = np.random.normal(size=(10000, 3), scale=0.2)

# 创建3D散点图
scatter = scene.visuals.Markers()
scatter.set_data(pos, edge_color=None, face_color=(1, 1, 1, 0.5), size=5)
view.add(scatter)

# 设置视角
view.camera = 'turntable'

canvas.app.run()
实时交互

Vispy支持鼠标和键盘等交互操作。以下示例展示了如何实现简单的鼠标交互:

from vispy import app, scene

canvas = scene.SceneCanvas(keys='interactive', show=True)
view = canvas.central_widget.add_view()

# 生成随机3D数据
pos = np.random.normal(size=(10000, 3), scale=0.2)

# 创建3D散点图
scatter = scene.visuals.Markers()
scatter.set_data(pos, edge_color=None, face_color=(1, 1, 1, 0.5), size=5)
view.add(scatter)

# 设置视角
view.camera = 'turntable'

# 定义鼠标点击事件
@canvas.events.mouse_press.connect
def on_mouse_press(event):
    print(f"Mouse clicked at {event.pos}")

canvas.app.run()

高级功能

创建自定义视觉元素

Vispy允许用户创建自定义的视觉元素。

以下示例展示了如何创建一个自定义的视觉元素:

import numpy as np
from vispy import gloo, app
from vispy.visuals import Visual
from vispy.visuals.transforms import STTransform
from vispy.scene.visuals import create_visual_node

class CustomVisual(Visual):
    VERTEX_SHADER = """
    attribute vec2 a_position;
    void main() {
        gl_Position = vec4(a_position, 0.0, 1.0);
    }
    """
    FRAGMENT_SHADER = """
    void main() {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
    """

    def __init__(self):
        super().__init__(self.VERTEX_SHADER, self.FRAGMENT_SHADER)
        self._vbo = gloo.VertexBuffer()
        self._program = gloo.Program(self.VERTEX_SHADER, self.FRAGMENT_SHADER)

    def set_data(self, data):
        self._vbo.set_data(data)
        self._program['a_position'] = self._vbo

    def _prepare_draw(self, view):
        pass

    def _prepare_transforms(self, view):
        pass

CustomNode = create_visual_node(CustomVisual)

canvas = scene.SceneCanvas(keys='interactive', show=True)
view = canvas.central_widget.add_view()
visual = CustomNode()
view.add(visual)

# 生成自定义数据
data = np.array([[-0.5, -0.5], [0.5, -0.5], [0.0, 0.5]], dtype=np.float32)
visual.set_data(data)

canvas.app.run()
使用文本和图像

Vispy支持在图形中添加文本和图像。

以下示例展示了如何在图形中添加文本:

from vispy import app, scene

canvas = scene.SceneCanvas(keys='interactive', show=True)
view = canvas.central_widget.add_view()

# 生成随机3D数据
pos = np.random.normal(size=(10000, 3), scale=0.2)

# 创建3D散点图
scatter = scene.visuals.Markers()
scatter.set_data(pos, edge_color=None, face_color=(1, 1, 1, 0.5), size=5)
view.add(scatter)

# 添加文本
text = scene.visuals.Text('Hello Vispy', color='white', anchor_x='center', anchor_y='center')
text.transform = STTransform(translate=(0, 0, 0))
view.add(text)

# 设置视角
view.camera = 'turntable'

canvas.app.run()

以下示例展示了如何在图形中添加图像:

import numpy as np
from vispy import app, scene
from vispy.io import load_data_file, read_png

canvas = scene.SceneCanvas(keys='interactive', show=True)
view = canvas.central_widget.add_view()

# 加载图像
image = read_png(load_data_file('mona_lisa/mona_lisa_sm.png'))
image_data = np.flipud(image)

# 创建图像视觉元素
image_visual = scene.visuals.Image(image_data, parent=view.scene)

# 设置视角
view.camera = 'panzoom'

canvas.app.run()
动态更新图形

Vispy允许动态更新图形,以实现实时数据可视化。

以下示例展示了如何动态更新2D散点图中的数据:

import numpy as np
from vispy import app, gloo, visuals

class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, keys='interactive')
        self.program = gloo.Program(visuals.MarkersVisual().vertex_shader, visuals.MarkersVisual().fragment_shader)
        self.data = np.random.rand(100, 2).astype(np.float32)
        self.program['a_position'] = self.data
        self.program['a_fg_color'] = np.ones((100, 4), dtype=np.float32)
        self.program['a_size'] = np.ones(100, dtype=np.float32) * 10
        gloo.set_state(clear_color='white', blend=True, blend_func=('src_alpha', 'one_minus_src_alpha'))
        self.timer = app.Timer('auto', self.on_timer)
        self.timer.start()
        self.show()

    def on_draw(self, event):
        gloo.clear()
        self.program.draw('points')

    def on_timer(self, event):
        self.data[:, 1] = np.random.rand(100)
        self.program['a_position'].set_data(self.data)
        self.update()

canvas = Canvas()
app.run()
交互式数据选择

Vispy支持用户与图形进行交互,例如选择和高亮数据点。

以下示例展示了如何实现交互式数据选择:

import numpy as np
from vispy import app, scene

class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, keys='interactive')
        self.unfreeze()
        self.view = self.central_widget.add_view()
        self.scatter = scene.visuals.Markers()
        self.view.add(self.scatter)
        self.data = np.random.rand(100, 2).astype(np.float32)
        self.scatter.set_data(self.data, face_color=(0, 0, 1, 1), size=5)
        self.view.camera = 'panzoom'
        self.freeze()

    def on_mouse_press(self, event):
        if event.button == 1:
            pos = event.pos
            tr = self.scatter.get_transform(map_to='canvas')
            trpos = tr.map(self.data)
            d = np.sqrt((trpos[:, 0] - pos[0]) ** 2 + (trpos[:, 1] - pos[1]) ** 2)
            idx = np.argmin(d)
            self.scatter.set_data(self.data, face_color=(0, 0, 1, 1), size=5)
            self.scatter.markers.set_data(self.data[idx:idx+1], face_color=(1, 0, 0, 1), size=10)
            self.update()

canvas = Canvas()
app.run()

实践应用

可视化分子结构

Vispy可以用于可视化科学数据,例如分子结构。

以下示例展示了如何可视化简单的分子结构:

import numpy as np
from vispy import scene
from vispy.visuals import Sphere, Tube

canvas = scene.SceneCanvas(keys='interactive', show=True)
view = canvas.central_widget.add_view()

# 创建分子结构数据
atoms = np.array([[0, 0, 0], [1, 1, 1], [-1, -1, -1]], dtype=np.float32)
bonds = np.array([[0, 1], [1, 2]], dtype=np.float32)

# 创建原子视觉元素
spheres = Sphere(radius=0.1, method='latitude', parent=view.scene)
spheres.transform = scene.transforms.MatrixTransform()
spheres.transform.translate(atoms)

# 创建键视觉元素
for bond in bonds:
    tube = Tube(points=atoms[bond], radius=0.05, method='cylinder', parent=view.scene)

# 设置视角
view.camera = 'turntable'

canvas.app.run()
机器学习结果可视化

以下示例展示了如何使用Vispy可视化机器学习模型的训练结果,例如损失和准确率的变化:

import numpy as np
from vispy import app, gloo

vertex_shader = """
uniform mat4 u_transform;
attribute vec2 a_position;
void main() {
    gl_Position = u_transform * vec4(a_position, 0.0, 1.0);
}
"""

fragment_shader = """
void main() {
    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
"""

class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, keys='interactive')
        self.program = gloo.Program(vertex_shader, fragment_shader)
        self.data = np.zeros((100, 2), dtype=np.float32)
        self.program['a_position'] = self.data
        self.program['u_transform'] = np.eye(4, dtype=np.float32)
        self.show()

    def on_draw(self, event):
        gloo.clear()
        self.program.draw('line_strip')

    def update_data(self, new_data):
        self.data[:, 1] = new_data
        self.program['a_position'].set_data(self.data)
        self.update()

canvas = Canvas()
canvas.update_data(np.random.rand(100))
app.run()
热力图可视化

Vispy支持绘制热力图,可以用于显示二维数据的密度或强度分布。

以下示例展示了如何使用Vispy绘制热力图:

import numpy as np
from vispy import scene, color

canvas = scene.SceneCanvas(keys='interactive', show=True)
view = canvas.central_widget.add_view()

# 生成二维数据
data = np.random.random((100, 100))

# 创建热力图视觉元素
heatmap = scene.visuals.Image(data, cmap='viridis', clim=(0, 1), parent=view.scene)

# 设置视角
view.camera = 'panzoom'

canvas.app.run()

总结

Vispy库为Python开发者提供了一个功能强大且灵活的高性能科学可视化工具。通过其简洁的API和丰富的功能,用户可以轻松地创建各种复杂的可视化应用,包括实时数据流、3D模型、分子结构、机器学习结果和热力图的可视化。本文详细介绍了Vispy库的安装、主要功能、基本操作、高级功能及其实践应用,并提供了丰富的示例代码。希望在实际项目中能够充分利用Vispy库,提高数据可视化的效率和效果。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐