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官网下载并安装。
以下示例展示了如何使用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)
以下示例展示了如何使用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库,提高数据可视化的效率和效果。