python - 如何制作多个移动点的动画?
问题描述
我正在尝试制作一个显示 100 个移动点的动画的脚本。每个点将走 100 步,之后,每个点都被不同的点替换,这将再走 100 步。我想像 1k 次(1000 代点)那样做这个过程。在每一代中——100 个点能够完成 100 个步骤。我从泡菜中读取坐标,但我不知道应该如何为这些动作设置动画。我写了一些代码,但我有点知道这是错误的,我不知道下一步该怎么做。我正在等待一些帮助;) PS:坐标保存为张量
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import pickle
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')
def init():
ax.set_xlim(0, 20)
ax.set_ylim(0, 20)
return ln,
def update(i):
with open("output.txt", "rb") as file:
try:
while True:
for point, coordinate in pickle.load(file).items():
for i in range(100):
if point == i:
xdata.append(coordinate.cpu().numpy()[0])
ydata.append(coordinate.cpu().numpy()[1])
ln.set_data(xdata, ydata)
return ln,
except EOFError:
pass
ani = FuncAnimation(fig, update, np.arange(1, 1000), init_func=init, blit=True)
plt.show()
output.txt
是一个巨大的文件,其内容是这样生成的:
output = open("output.txt", "wb")
for i in range(number_of_points):
self.points[i].point_step()
points = { i: self.points[i].point_location }
pickle.dump(points, output)
output.close()
解决方案
如果我理解正确,文件 ,output.txt
包含一系列腌制的字典。每个字典的形式
{ i: self.points[i].point_location }
每次调用update
都应从此文件中读取 100 个(新)字典。我们可以通过创建一个生成器函数来做到这一点,get_data
它一次从文件中生成一个项目。然后定义
data = get_data(path)
在外部update
并将其update
作为参数传递给(使用FuncAnimation
'sfargs
参数。) 在内部update
,循环
for point, coordinate in itertools.islice(data, 100):
遍历 100 个项目data
。由于data
是一个迭代器,每次调用它itertools.islice
都会产生 100 个新项目。data
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import pickle
import itertools as IT
def init():
ax.set_xlim(0, 20)
ax.set_ylim(0, 20)
return (pathcol,)
def pickleLoader(f):
"""
Return generator which yields unpickled objects from file object f
# Based on https://stackoverflow.com/a/18675864/190597 (Darko Veberic)
"""
try:
while True:
yield pickle.load(f)
except EOFError:
pass
def get_data(path):
with open(path, "rb") as f:
for dct in pickleLoader(f):
yield from dct.items()
def update(i, data, pathcol, texts, title, num_points):
title.set_text("Generation {}".format(i))
xdata, ydata, color = [], [], []
for point, coordinate in IT.islice(data, num_points):
texti = texts[point]
x, y = coordinate.cpu().numpy()
xdata.append(x)
ydata.append(y)
color.append(point)
texti.set_position((x, y))
color = np.array(color, dtype="float64")
color /= num_points
pathcol.set_color = color
pathcol.set_offsets(np.column_stack([xdata, ydata]))
return [pathcol, title] + texts
class Coord:
# just to make the code runnable
def __init__(self, coord):
self.coord = coord
def cpu(self):
return Cpu(self.coord)
class Cpu:
# just to make the code runnable
def __init__(self, coord):
self.coord = coord
def numpy(self):
return self.coord
def make_data(path, num_frames=1000, num_points=100):
# just to make the code runnable
with open(path, "wb") as output:
for frame in range(num_frames):
for i in range(num_points):
points = {i: Coord(20 * np.random.random((2,)))}
pickle.dump(points, output)
def _blit_draw(self, artists, bg_cache):
# https://stackoverflow.com/a/17562747/190597 (tacaswell)
# Handles blitted drawing, which renders only the artists given instead
# of the entire figure.
updated_ax = []
for a in artists:
# If we haven't cached the background for this axes object, do
# so now. This might not always be reliable, but it's an attempt
# to automate the process.
if a.axes not in bg_cache:
# bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox)
# change here
bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.figure.bbox)
a.axes.draw_artist(a)
updated_ax.append(a.axes)
# After rendering all the needed artists, blit each axes individually.
for ax in set(updated_ax):
# and here
# ax.figure.canvas.blit(ax.bbox)
ax.figure.canvas.blit(ax.figure.bbox)
# MONKEY PATCH!!
matplotlib.animation.Animation._blit_draw = _blit_draw
num_points = 100
num_frames = 1000
fig, ax = plt.subplots()
pathcol = ax.scatter(
[0] * num_points, [0] * num_points, c=np.linspace(0, 1, num_points), s=100
)
title = ax.text(
0.5,
1.05,
"",
transform=ax.transAxes,
horizontalalignment="center",
fontsize=15,
animated=True,
)
texts = []
for i in range(num_points):
t = ax.text(0, 0, str(i), fontsize=10, animated=True)
texts.append(t)
path = "/tmp/output.txt"
make_data(path, num_frames, num_points) # just to make the code runnable
data = get_data(path)
ani = FuncAnimation(
fig,
update,
range(1, num_frames + 1),
init_func=init,
blit=True,
fargs=(data, pathcol, texts, title, num_points),
interval=1000, # decrease to speed up the animation
repeat=False,
)
plt.show()
推荐阅读
- matlab - 以相等的递增间隔生成随机数
- c++ - 错误:操作数类型 std::vector::iterator 和 __gnu_cxx::__normal_iterator 的 'operator=' 不匹配
- javascript - Symfony 5:Ux Turbo Pusher 消息重复
- java - Spring存储库如何根据字段的ID在列表中查找?
- r - ggplot中带有圆圈而不是瓷砖的热图
- java - 如何将 TXT 文件写入“/storage/emulated/0/myapp/myfile.txt”,以便稍后从文件浏览器打开它们?
- python - 为指数分布创建对数似然函数?
- go - GoTa 系列显示 NaN,但调试器显示值
- amazon-cloudformation - 如何生成 YAML 格式的 Canformation 模板?
- php - 在 PHP 中使用接口有什么好处,它的真正用途在哪里?