假设我有一组数据,由时间序列和X、Y、Z千点坐标组成(示例数据如下)。我想以 3D 方式绘制数据,就像地球绕太阳运行一样,或者地球绕太阳运行并带有 10 个褪色地球的轨迹。
通过遵循 3D 示例代码,目前我能够同时绘制所有点并进行淡入淡出。但我不知道如何迭代这些点并使用计时器正确启动/停止来更新绘图。
(轨道.csv)
TimeDiff,X,Y,Z
0.0,0.00,0.27,-8.28
0.04,-0.96,0.27,-11.46
0.17,-0.96,-0.18,-13.81
0.36,-2.69,-0.18,-16.34
0.5,-2.69,-0.77,-17.69
0.73,-4.82,-0.77,-19.20
0.83,-4.82,-0.99,-19.43
1.04,-6.10,-0.99,-19.68
1.18,-6.10,-0.84,-18.87
1.39,-4.20,-0.84,-17.49
1.5,-4.20,-0.65,-15.63
1.72,-2.09,-0.65,-13.38
1.83,-2.09,-0.31,-10.49
2.05,-0.92,-0.31,-7.47
2.18,-0.92,0.09,-4.10
2.36,-0.12,0.09,-0.58
2.52,-0.12,0.20,2.71
2.7,-0.05,0.20,6.11
2.86,-0.05,0.11,9.12
3.03,-0.89,0.11,12.30
3.18,-0.89,-0.29,14.46
或降价格式:
| Time | X | Y | Z |
| -------- | ----- | ----- | ------ |
| 0 | 0 | 0.27 | -8.28 |
| 0.04 | -0.96 | 0.27 | -11.46 |
| 0.17 | -0.96 | -0.18 | -13.81 |
| 0.36 | -2.69 | -0.18 | -16.34 |
| 0.5 | -2.69 | -0.77 | -17.69 |
| 0.73 | -4.82 | -0.77 | -19.2 |
| 0.83 | -4.82 | -0.99 | -19.43 |
| 1.04 | -6.1 | -0.99 | -19.68 |
| 1.18 | -6.1 | -0.84 | -18.87 |
| 1.39 | -4.2 | -0.84 | -17.49 |
| 1.5 | -4.2 | -0.65 | -15.63 |
| 1.72 | -2.09 | -0.65 | -13.38 |
| 1.83 | -2.09 | -0.31 | -10.49 |
| 2.05 | -0.92 | -0.31 | -7.47 |
| 2.18 | -0.92 | 0.09 | -4.1 |
| 2.36 | -0.12 | 0.09 | -0.58 |
| 2.52 | -0.12 | 0.2 | 2.71 |
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets
import pyqtgraph.opengl as gl
from pyqtgraph import functions as fn
import numpy as np
import pandas as pd
import os
app = QtWidgets.QApplication([])
w = gl.GLViewWidget()
w.opts['distance'] = 500
w.show()
w.setWindowTitle('pyqtgraph example: GLVolumeItem')
ax = gl.GLAxisItem()
ax.setSize(900, 900, 900)
w.addItem(ax)
f = "Orbit.csv"
df = pd.read_csv(f)
timeList = df['TimeDiff'].tolist()
comp_x = df["X"].tolist()
comp_y = df["Y"].tolist()
comp_z = df["Z"].tolist()
w.setWindowTitle('pyqtgraph example: DateAxisItem')
speed = 1
measureTimeList = [x / speed for x in timeList]
line_x = [x for x in comp_x]
line_y = [x for x in comp_y]
line_z = [x for x in comp_z]
pos = np.empty((len(line_x), 3))
size = np.empty(len(line_x))
color = np.empty((len(line_x), 4))
pos[2] = (0, 0, 1);
size[2] = 1. / 1.0;
color[2] = (0.0, 1.0, 0.0, 1)
def update(): ## update volume colors
global phase, sp2, d2
s = -np.cos(d2*2+phase)
color = np.empty((len(line_x), 4), dtype=np.float32)
color[:, 3] = fn.clip_array(s * 0.1, 0., 1.)
color[:, 0] = fn.clip_array(s * 3.0, 0., 1.)
color[:, 1] = fn.clip_array(s * 1.0, 0., 1.)
color[:, 2] = fn.clip_array(s ** 3, 0., 1.)
sp2.setData(color=color)
phase -= 0.1
t = QtCore.QTimer()
t.timeout.connect(update)
t.start(20)
color = np.ones((pos.shape[0], 4))
for i in range(len(line_x)):
pos[i] = (line_z[i], line_x[i], line_y[i])
d2 = 2
phase = 90.
size = 2
s = -np.cos(d2 * 2 + phase)
color[:, 3] = fn.clip_array(s * 0.1, 0., 1.)
color[:, 0] = fn.clip_array(s * 3.0, 0., 1.)
color[:, 1] = fn.clip_array(s * 1.0, 0., 1.)
color[:, 2] = fn.clip_array(s ** 3, 0., 1.)
sp2 = gl.GLScatterPlotItem(pos=pos, color=(1, 1, 1, 1), size=size)
w.addItem(sp2)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtWidgets.QApplication.instance().exec_()
不幸的是,我在您的数据中没有看到轨道。尽管如此,这是我的方法:
将所有颜色设置为完全透明。然后创建一个从 0 到 1 的“透明度渐变”,并让这个渐变“滚动”到每次更新的位置上。这样,它看起来就像一个移动的褪色物体:
from pyqtgraph.Qt import QtCore, QtWidgets
import pyqtgraph.opengl as gl
import numpy as np
import pandas as pd
app = QtWidgets.QApplication([])
w = gl.GLViewWidget()
w.opts["distance"] = 100
w.show()
ax = gl.GLAxisItem()
ax.setSize(900, 900, 900)
w.addItem(ax)
df = pd.read_csv("Orbit.csv")
frame_count = 0
def update():
global frame_count, sp2
# create transparency ramp over n_display positions
n_display = 6
color = np.ones((sp2.pos.shape[0], 4), dtype=np.float32)
color[:, 3] = 0
color[: n_display + 1, 3] = np.linspace(0, 1, n_display + 1)
# move the ramp over the array with increasing frame_count
color = np.roll(color, frame_count, axis=0)
frame_count += 1
sp2.setData(color=color)
t = QtCore.QTimer()
t.timeout.connect(update)
t.start(100)
pos = [(z, x, y) for z, x, y in zip(df["Z"], df["X"], df["Y"])]
sp2 = gl.GLScatterPlotItem(pos=pos, color=(1, 1, 1, 1), size=5)
w.addItem(sp2)
if __name__ == "__main__":
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, "PYQT_VERSION"):
QtWidgets.QApplication.instance().exec()