Создание 3D-диаграммы рассеяния в стиле Matplotlib в Vispy
Я провожу аспирантуру по исследованию облаков точек лидара чрезвычайно высокой плотности (1М точек +) и испытываю трудности с нанесением этих файлов на 3D-диаграмму рассеяния. Matplotlib не оптимизирован для таких больших наборов данных, поэтому я пытаюсь использовать Vispy для достижения этой цели. Прямо сейчас у меня есть реальная проблема, пытаясь получить график в стиле разброса, чтобы я мог начать строить свой конвейер.
Я после чего-то вроде этого: Matplotlib 3D Scattergraph
Используя Vispy, мне трудно применить ось Z, и мне трудно найти, какая часть документации может помочь мне в этом. Вот мой код:
"""
This example demonstrates the use of the SurfacePlot visual.
"""
import sys
import numpy as np
from vispy import app, scene
from vispy.util.filter import gaussian_filter
canvas = scene.SceneCanvas(keys='interactive', bgcolor='w')
view = canvas.central_widget.add_view()
view.camera = scene.TurntableCamera(up='z', fov=60)
# Simple surface plot example
# x, y values are not specified, so assumed to be 0:50
z = np.random.normal(size=(250, 250), scale=200)
z[100, 100] += 50000
z = gaussian_filter(z, (10, 10))
print("This is z {0}".format(z))
p1 = scene.visuals.SurfacePlot(z=z, color=(0.3, 0.3, 1, 1))
p1.transform = scene.transforms.MatrixTransform()
p1.transform.scale([1/249., 1/249., 1/249.])
p1.transform.translate([-0.5, -0.5, 0])
view.add(p1)
# p1._update_data() # cheating.
# cf = scene.filters.ZColormapFilter('fire', zrange=(z.max(), z.min()))
# p1.attach(cf)
xax = scene.Axis(pos=[[-0.5, -0.5], [0.5, -0.5]], tick_direction=(0, -1),
font_size=16, axis_color='k', tick_color='k', text_color='k',
parent=view.scene)
xax.transform = scene.STTransform(translate=(0, 0, -0.2))
yax = scene.Axis(pos=[[-0.5, -0.5], [-0.5, 0.5]], tick_direction=(-1, 0),
font_size=16, axis_color='k', tick_color='k', text_color='k',
parent=view.scene)
yax.transform = scene.STTransform(translate=(0, 0, -0.2))
zax = scene.Axis(pos=[[1.0, 1.0], [-1.0, 1.0]], tick_direction=(-1, 0),
font_size=16, axis_color='k', tick_color='k', text_color='k',
parent=view.scene)
zax.transform = scene.STTransform(translate=(0.0, 0.0, -0.2))
# Add a 3D axis to keep us oriented
axis = scene.visuals.XYZAxis(parent=view.scene)
if __name__ == '__main__':
canvas.show()
if sys.flags.interactive == 0:
app.run()
И это делает график, который выглядит так:
Вы можете видеть на изображении выше мою проблему. Я хочу ориентировать третью ось перпендикулярно другим, а сетку - к стенам графика, чтобы данные были более определенными.
К сожалению, дополнительная выборка и другие приемы отображения данных с помощью matplotlib не являются оптимальными для меня, потому что мне нужно отображать исходные данные, а не показывать подмножество. Конечно, если есть другие стратегии, которые я могу использовать для отображения своих данных так, как мне хочется, тогда я весь в ушах.
Заранее спасибо, надеюсь, кто-то может помочь
1 ответ
Я столкнулся с той же проблемой, занимаясь исследованиями глубины изображения с камеры и радиолокационных данных. Так как vispy поддерживает 2d только для осей, вы можете вращать ось Z после создания. здесь немного измененная версия вашего кода:
import sys
import numpy as np
from vispy import app, scene
from vispy.util.filter import gaussian_filter
canvas = scene.SceneCanvas(keys='interactive', bgcolor='w')
view = canvas.central_widget.add_view()
view.camera = scene.TurntableCamera(up='z', fov=60)
z = np.random.normal(size=(250, 250), scale=200)
z[100, 100] += 50000
z = gaussian_filter(z, (10, 10))
p1 = scene.visuals.SurfacePlot(z=z, color=(0.3, 0.3, 1, 1))
p1.transform = scene.transforms.MatrixTransform()
p1.transform.scale([1/249., 1/249., 1/249.])
view.add(p1)
xax = scene.Axis(pos=[[0, 0], [1, 0]], tick_direction=(0, -1), axis_color='r', tick_color='r', text_color='r', font_size=16, parent=view.scene)
yax = scene.Axis(pos=[[0, 0], [0, 1]], tick_direction=(-1, 0), axis_color='g', tick_color='g', text_color='g', font_size=16, parent=view.scene)
zax = scene.Axis(pos=[[0, 0], [-1, 0]], tick_direction=(0, -1), axis_color='b', tick_color='b', text_color='b', font_size=16, parent=view.scene)
zax.transform = scene.transforms.MatrixTransform() # its acutally an inverted xaxis
zax.transform.rotate(90, (0, 1, 0)) # rotate cw around yaxis
zax.transform.rotate(-45, (0, 0, 1)) # tick direction towards (-1,-1)
if __name__ == '__main__':
canvas.show()
if sys.flags.interactive == 0:
app.run()
С уважением