使用 jupyter 中的plotly,我正在创建一个 Scatter3D 图,如下所示:
# Configure the trace.
trace = go.Scatter3d(
x=x,
y=y,
z=z,
mode='markers',
marker=dict(color=colors, size=1)
)
# Configure the layout.
layout = go.Layout(
margin={'l': 0, 'r': 0, 'b': 0, 't': 0},
height = 1000,
width = 1000
)
data = [trace]
plot_figure = go.Figure(data=data, layout=layout)
# Render the plot.
plotly.offline.iplot(plot_figure)
如何旋转这样生成的绘图,以便从中创建 gif 视频,即存储为 gif 文件,如
rotate.gif
,它显示旋转绘图的动画?
根据给出的评论,我创建了这段代码(完整的工作示例):
import plotly.graph_objects as go
import numpy as np
import plotly.io as pio
# Helix equation
t = np.linspace(0, 10, 50)
x, y, z = np.cos(t), np.sin(t), t
fig= go.Figure(go.Scatter3d(x=x, y=y, z=z, mode='markers'))
x_eye = -1.25
y_eye = 2
z_eye = 0.5
fig.update_layout(
title='Animation Test',
width=600,
height=600,
scene_camera_eye=dict(x=x_eye, y=y_eye, z=z_eye),
updatemenus=[dict(type='buttons',
showactive=False,
y=1,
x=0.8,
xanchor='left',
yanchor='bottom',
pad=dict(t=45, r=10),
buttons=[dict(label='Play',
method='animate',
args=[None, dict(frame=dict(duration=5, redraw=True),
transition=dict(duration=1),
fromcurrent=True,
mode='immediate'
)]
)
]
)
]
)
def rotate_z(x, y, z, theta):
w = x+1j*y
return np.real(np.exp(1j*theta)*w), np.imag(np.exp(1j*theta)*w), z
frames=[]
for k, t in enumerate(np.arange(0, 6.26, 0.1)):
xe, ye, ze = rotate_z(x_eye, y_eye, z_eye, -t)
newframe = go.Frame(layout=dict(scene_camera_eye=dict(x=xe, y=ye, z=ze)))
frames.append(newframe)
pio.write_image(newframe, f"images/images_{k+1:03d}.png", width=400, height=400, scale=1)
fig.frames=frames
fig.show()
运行时没有错误,并且当我按下“播放”时会旋转场景,但是保存的图像仅显示一个空的 2D 坐标系:
但不是我实际看到的旋转。这些图像似乎是在我执行 jupyter 笔记本中的单元格时创建的,而不是在我按“播放”后创建的。似乎有两个图形,一个我可以看到旋转,另一个是保存到文件中的空 2D 坐标系的图像......
下面这个更接近。不过,我怀疑我们需要解决尺寸和缩放问题。
import plotly.graph_objects as go
import numpy as np
import plotly.io as pio
# Helix equation
t = np.linspace(0, 10, 50)
x, y, z = np.cos(t), np.sin(t), t
fig= go.Figure(go.Scatter3d(x=x, y=y, z=z, mode='markers'))
x_eye = -1.25
y_eye = 2
z_eye = 0.5
fig.update_layout(
title='Animation Test',
width=600,
height=600,
scene_camera_eye=dict(x=x_eye, y=y_eye, z=z_eye),
updatemenus=[dict(type='buttons',
showactive=False,
y=1,
x=0.8,
xanchor='left',
yanchor='bottom',
pad=dict(t=45, r=10),
buttons=[dict(label='Play',
method='animate',
args=[None, dict(frame=dict(duration=5, redraw=True),
transition=dict(duration=0),
fromcurrent=True,
mode='immediate'
)]
)
]
)
]
)
def rotate_z(x, y, z, theta):
w = x+1j*y
return np.real(np.exp(1j*theta)*w), np.imag(np.exp(1j*theta)*w), z
frames=[]
for k,t in enumerate(np.arange(0, 1.26, 0.1)):
xe, ye, ze = rotate_z(x_eye, y_eye, z_eye, -t)
frames.append(go.Frame(layout=dict(scene_camera_eye=dict(x=xe, y=ye, z=ze))))
current_fig = go.Figure(fig.data, layout=dict(scene_camera_eye=dict(x=xe, y=ye, z=ze)))
pio.write_image(current_fig, f"images/images_{k+1:03d}.png", width=400, height=400, scale=1)
fig.frames=frames
fig.show()
在您更新的代码中,看起来您正在使用此代码并尝试根据我在
此处指出的
pio.write_image()
的使用添加图形的保存。 (我真的不明白 Play
按钮对于您的情况的用途,除了它可以让您像这样检查开发中的工作情况。虽然它可能是您最终想要分享的混乱动画。).png
文件的帧所需的内容。
具有以下内容:
newframe = go.Frame(layout=dict(scene_camera_eye=dict(x=xe, y=ye, z=ze)))
frames.append(newframe)
pio.write_image(newframe, f"images/images_{k+1:03d}.png", width=400, height=400, scale=1)
您正在向
pio.write_image
发送一个框架对象。我认为您想要带有原始数据的图形,因此您需要使用类似于 此 Plotly 问题“获取动画帧”的回复中所涵盖的内容来重建该图形。
所以现在我更改了代码以使用您用于框架的布局,但使用该布局和原始数据制作一个图形。