Кодирование анимированного графика рассеяния из массивов - PullRequest
1 голос
/ 23 февраля 2020

Я пытаюсь кодировать модель Vicsek и создал массивы, содержащие координаты x и y для каждой точки в определенные c раз. Затем я вызываю значения x и y для каждого временного интервала и помещаю их в списки. Данные представлены в виде двух списков, один для х и один для у. Я пытаюсь анимировать его следующим образом:

fig = plt.figure()
ax = fig.add_subplot(111)
scat = plt.scatter(x, y, c = x)
scat.set_alpha(0.8)

ax.set_xlim(-L/2, L/2)
ax.set_ylim(-L/2, L/2)

def animate_frames(i, fig, scat):
    a = P[i]
    xi = []
    yi = []
    for v in range(N):
        xi.append(a[v,0])
        yi.append(a[v,1])
    A = np.transpose([xi,yi])
    scat.set_offsets((A))
    return scat 

animation = FuncAnimation(fig, func=animate_frames, fargs=(fig,scat), frames= tmax, interval = 1000)
plt.show()

Где P[i] вызывает массив, в котором я хранил значения x и y моих точек на каждом временном интервале i. (в P есть записи tmax)

Я получаю точечный график, который затем часто мигает другим, но не анимацию.

Я новичок в Python и буду благодарен за любую помощь, которую я смогу получить.

1 Ответ

0 голосов
/ 24 февраля 2020

Кажется, нет ничего плохого в том, как вы пытаетесь анимировать график рассеяния (кроме некоторых незначительных проблем, таких как передача переменных, которые вам не нужно передавать). Я подозреваю, что либо ваш параметр скорости, либо ваш параметр шума слишком велик (при вычислении обновленных положений точек), так что, похоже, нет непрерывности между графиками.

Ниже приведена справочная реализация. Если вы поиграете с параметром шума eta, вы увидите, что обновления появляются с перерывами.

enter image description here

#!/usr/bin/env python
"""
Simple scatter plot animation.
"""
import numpy as np
import matplotlib.pyplot as plt

from matplotlib.animation import FuncAnimation
from scipy.spatial import cKDTree


# def update_positions(x, y, v=0.01):
#     # random diffusion
#     dx, dy = np.random.randn(2, 100)
#     x += v*dx
#     y += v*dy
#     return x, y


def get_mean_angle(angles):
    # https://stackoverflow.com/a/491769/2912349
    # convert to unit vectors
    x = np.cos(angles)
    y = np.sin(angles)
    X = np.c_[x, y]
    U = X / np.linalg.norm(X)
    # get mean unit vector
    x, y = np.mean(X, axis=0)
    return np.arctan2(y, x)


def update_positions(x, y, theta, eta=0.1, r=0.1, v=0.01):
    # https://en.wikipedia.org/wiki/Vicsek_model
    X = np.c_[x,y]
    tree = cKDTree(X)
    neighbours = tree.query_ball_tree(tree, r=r)
    for ii, nn in enumerate(neighbours):
        theta[ii] = get_mean_angle(theta[nn]) + 2*np.pi*np.random.rand()*eta

    X += v * np.c_[np.cos(theta), np.sin(theta)]
    x, y = X.T
    return x, y, theta


if __name__ == '__main__':

    total_points = 100
    x, y = np.random.rand(2, total_points)
    theta = 2*np.pi*np.random.rand(total_points)

    fig, ax = plt.subplots(1,1)
    scatter = ax.scatter(x, y)

    def animate_frames(ii, x, y, theta):
        x, y, theta = update_positions(x, y, theta)
        scatter.set_offsets(np.c_[x, y])
        return scatter

    animation = FuncAnimation(fig, fargs=(x,y,theta), func=animate_frames, frames=20)
    animation.save('vicsek.gif', writer='imagemagick',  savefig_kwargs={'facecolor':'white'}, fps=5)
    plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...