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库,提高数据可视化的效率和效果。