Я написал код для симуляции n-body, который хотел бы оживить. Есть много вопросов о том, как использовать matplotlib для создания анимации;некоторые из них ( как этот и этот ) упоминают более сложный случай одновременной анимации нескольких наборов данных. Я пытаюсь включить вещи из этих ответов в методы класса, чтобы я мог создать статическое изображение или анимацию. Я сделал статичное изображение, но не могу понять свою ошибку при попытке создать анимацию. Мой вопрос касается только аспекта анимации;предыдущие позиции каждого тела хранятся в виде массивов. Как пример:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation
class Body():
def __init__(self, identifier, facecolor, position, previous_positions):
""" """
self.identifier = identifier
self.facecolor = facecolor
self.position = position
self.previous_positions = previous_positions
def __str__(self):
res = ''
keys = ('identifier', 'facecolor', 'position', 'previous_positions')
values = (self.identifier, self.facecolor, self.position, self.previous_positions)
for key, value in zip(keys, values):
res += '\n .. {}:\n{}\n'.format(key, value)
return res
nmoments, ndim = 10, 2
ts = np.arange(nmoments)
apos = np.array([np.cos(ts), np.sin(ts)]).T
bpos = np.array([-np.sin(ts), np.cos(ts)]).T
cpos = np.array([np.zeros(ts.shape), np.cos(np.pi * ts)]).T
A = Body('A', 'red', position=apos[-1], previous_positions=apos)
B = Body('B', 'blue', position=bpos[-1], previous_positions=bpos)
C = Body('C', 'orange', position=cpos[-1], previous_positions=cpos)
bodies = (A, B, C)
# for body in bodies:
# print(body)
Теперь у нас есть 3 набора данных (A
, B
и C
), каждый из которых имеет свои собственные позиции в зависимости от времени ts
. Так как мой код, содержащий симуляцию nbody, имеет class NBody
, я хотел бы дать ему метод, который я мог бы вызвать как:
NB = NBody(bodies, ...) # initialize instance of class
NB.simulate(...) # update positions as time updates
NB.animate(...) # use updated positions to create animation
Я могу сделать это, если у меня есть класс Visualizer
, чья единственнаяцелью является создание изображений и анимации;затем разбейте его на подклассы, как показано ниже:
class NBody(Visualizer):
super().__init__(...)
Моя попытка на основе SO вопросов и ответов создать анимацию с использованием этого подхода приведена ниже:
class Visualizer():
def __init__(self, bodies, nmoments):
""" """
self.bodies = bodies
self.ndim = bodies[0].position.shape[0]
self.nmoments = nmoments
def get_figure_and_axes(self, **kwargs):
""" """
if self.ndim == 2:
fig, ax = plt.subplots(**kwargs)
elif self.ndim == 3:
fig = plt.figure(**kwargs)
ax = fig.add_subplot(1, 1, 1, projection='3d')
else:
raise ValueError("invalid ndim: {}; ndim = 2 or 3".format(self.ndim))
return fig, ax
def initialize_animation_axes(self, ax):
""" """
lines = [ax.plot(*ibody.position, color=ibody.facecolor)[0] for ibody in self.bodies]
ax.set_xlim([-2, 2])
ax.set_ylim([-2, 2])
self.lines = lines
def animate(self, ith_moment):
""" """
for ith_body, ibody in enumerate(self.bodies):
coords = ibody.previous_positions[ith_moment] # [ith_moment, :]
self.lines[ith_body].set_data(*coords)
return self.lines
V = Visualizer(bodies, nmoments)
fig, ax = V.get_figure_and_axes()
V.initialize_animation_axes(ax)
anim = matplotlib.animation.FuncAnimation(fig, V.animate)
plt.show()
plt.close(fig)
Фигура изначально выглядит пустой,и затем для каждого кадра возникает новая ошибка, пока анимация не будет завершена / закрыта. Ошибка обратной трассировки показана ниже для первых нескольких итераций;Главное, на что нужно обратить внимание: IndexError: index ii is out of bounds for axis 0 with size 10
, где ii
начинается с 10
.
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/backend_bases.py", line 1373, in _on_timer
ret = func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1481, in _step
still_going = Animation._step(self, *args)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1217, in _step
self._draw_next_frame(framedata, self._blit)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1236, in _draw_next_frame
self._draw_frame(framedata)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "soq1.py", line 66, in animate
coords = ibody.previous_positions[ith_moment] # [ith_moment, :]
IndexError: index 10 is out of bounds for axis 0 with size 10
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/backend_bases.py", line 1373, in _on_timer
ret = func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1481, in _step
still_going = Animation._step(self, *args)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1217, in _step
self._draw_next_frame(framedata, self._blit)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1236, in _draw_next_frame
self._draw_frame(framedata)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "soq1.py", line 66, in animate
coords = ibody.previous_positions[ith_moment] # [ith_moment, :]
IndexError: index 11 is out of bounds for axis 0 with size 10
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/backend_bases.py", line 1373, in _on_timer
ret = func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1481, in _step
still_going = Animation._step(self, *args)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1217, in _step
self._draw_next_frame(framedata, self._blit)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1236, in _draw_next_frame
self._draw_frame(framedata)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "soq1.py", line 66, in animate
coords = ibody.previous_positions[ith_moment] # [ith_moment, :]
IndexError: index 12 is out of bounds for axis 0 with size 10
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/backend_bases.py", line 1373, in _on_timer
ret = func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1481, in _step
still_going = Animation._step(self, *args)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1217, in _step
self._draw_next_frame(framedata, self._blit)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1236, in _draw_next_frame
self._draw_frame(framedata)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "soq1.py", line 66, in animate
coords = ibody.previous_positions[ith_moment] # [ith_moment, :]
IndexError: index 13 is out of bounds for axis 0 with size 10
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/backend_bases.py", line 1373, in _on_timer
ret = func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1481, in _step
still_going = Animation._step(self, *args)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1217, in _step
self._draw_next_frame(framedata, self._blit)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1236, in _draw_next_frame
self._draw_frame(framedata)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "soq1.py", line 66, in animate
coords = ibody.previous_positions[ith_moment] # [ith_moment, :]
IndexError: index 14 is out of bounds for axis 0 with size 10
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/backend_bases.py", line 1373, in _on_timer
ret = func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1481, in _step
still_going = Animation._step(self, *args)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1217, in _step
self._draw_next_frame(framedata, self._blit)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1236, in _draw_next_frame
self._draw_frame(framedata)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "soq1.py", line 66, in animate
coords = ibody.previous_positions[ith_moment] # [ith_moment, :]
IndexError: index 15 is out of bounds for axis 0 with size 10
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/backend_bases.py", line 1373, in _on_timer
ret = func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1481, in _step
still_going = Animation._step(self, *args)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1217, in _step
self._draw_next_frame(framedata, self._blit)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1236, in _draw_next_frame
self._draw_frame(framedata)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "soq1.py", line 66, in animate
coords = ibody.previous_positions[ith_moment] # [ith_moment, :]
IndexError: index 16 is out of bounds for axis 0 with size 10
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/backend_bases.py", line 1373, in _on_timer
ret = func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1481, in _step
still_going = Animation._step(self, *args)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1217, in _step
self._draw_next_frame(framedata, self._blit)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1236, in _draw_next_frame
self._draw_frame(framedata)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "soq1.py", line 66, in animate
coords = ibody.previous_positions[ith_moment] # [ith_moment, :]
IndexError: index 17 is out of bounds for axis 0 with size 10
Я не до конца понимаю, что делает matplotlib в фоновом режиме (несмотря на просмотр их документов). Что я здесь не так делаю?