3D动画与matplotlib,连接点来创建移动简笔画 [英] 3D animation with matplotlib, connect points to create moving stick figure

查看:2013
本文介绍了3D动画与matplotlib,连接点来创建移动简笔画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前遇到一些麻烦我的code这部分动画的时间序列数据,我不能完全弄清楚。基本上,我有12个标签,我正在通过时间动画。每个标签都有时间,使得移动路径可以看到了,因为它的进展每个标签的轨迹(看看附图片)。现在我想的动画还包括对标记之间的线(即对点 - 例如,如何添加黄色和绿色标签之间的动画线),但我不完全知道如何做到这一点。这是code改编自jakevdp.github.io。

I am currently having some trouble with my code which animates some time-series data, and I cannot quite figure it out. Basically I have 12 tags which I am animating through time. Each tag has a trajectory in time such that the movement path can be seen for each tag as it progresses (have a look at the image attached). Now I would like the animation to also include the lines between pairs of tags (i.e. pairs of points - for example, how to add an animation line between the yellow and green tags), but I am not entirely sure how to do this. This is code adapted from jakevdp.github.io.

下面是code迄今。

Here is the code thus far.

"""
Full animation of a walking event (note: a lot of missing data) 
"""
import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('TkAgg') # Need to use in order to run on mac
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.colors import cnames
from matplotlib import animation

#=============================================================================================

t_start = 1917 # start frame
t_end = 2130 # end frame

data = pd.read_csv('~/Smart-first_phase_NaN-zeros.csv') # only coordinate data
df = data.loc[t_start:t_end,'Shoulder_left_x':'Ankle_right_z']

# Find max and min values for animation ranges
df_minmax = pd.DataFrame(index=list('xyz'),columns=range(2))
for i in list('xyz'):
    c_max = df.filter(regex='_{}'.format(i)).max().max()
    c_min = df.filter(regex='_{}'.format(i)).min().min()
    df_minmax.ix[i] = np.array([c_min,c_max])

df_minmax = 1.3*df_minmax # increase by 30% to make animation look better

df.columns  = np.repeat(range(12),3) # store cols like this for simplicity
N_tag = df.shape[1]/3 # nr of tags used (all)

N_trajectories = N_tag

t = np.linspace(0,data.Time[t_end],df.shape[0]) # pseudo time-vector for first walking activity
x_t = np.zeros(shape=(N_tag,df.shape[0],3)) # empty animation array (3D)

for tag in range(12):
    # store data in numpy 3D array: (tag,time-stamp,xyz-coordinates)
    x_t[tag,:,:] = df[tag]


#===STICK-LINES========================================================================================
#xx = [x_t[1,:,0],x_t[2,:,0]]
#yy = [x_t[1,:,1],x_t[2,:,1]]
#zz = [x_t[1,:,2],x_t[2,:,2]] 
#======================================================================================================

# Set up figure & 3D axis for animation
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1], projection='3d')
ax.axis('on')

# choose a different color for each trajectory
colors = plt.cm.jet(np.linspace(0, 1, N_trajectories))
# set up trajectory lines
lines = sum([ax.plot([], [], [], '-', c=c) for c in colors], [])
# set up points
pts = sum([ax.plot([], [], [], 'o', c=c) for c in colors], [])
# set up lines which create the stick figures
stick_lines = sum([ax.plot([], [], [], '-', c=c) for c in colors], [])

# prepare the axes limits
ax.set_xlim(df_minmax.ix['x'].values)
ax.set_ylim(df_minmax.ix['z'].values) # note usage of z coordinate
ax.set_zlim(df_minmax.ix['y'].values) # note usage of y coordinate

# set point-of-view: specified by (altitude degrees, azimuth degrees)
ax.view_init(30, 0)

# initialization function: plot the background of each frame
def init():
    for line, pt, stick_line in zip(lines, pts, stick_lines):
        # trajectory lines
        line.set_data([], [])
        line.set_3d_properties([])
        # points
        pt.set_data([], [])
        pt.set_3d_properties([])
        # stick lines
        stick_line.set_data([], [])
        stick_line.set_3d_properties([])
    return lines + pts + stick_lines

# animation function.  This will be called sequentially with the frame number
def animate(i):
    # we'll step two time-steps per frame.  This leads to nice results.
    i = (5 * i) % x_t.shape[1]

    for line, pt, stick_line, xi in zip(lines, pts, stick_lines, x_t):
        x, z, y = xi[:i].T # note ordering of points to line up with true exogenous registration (x,z,y)
        # trajectory lines
        line.set_data(x,y)
        line.set_3d_properties(z)
        # points
        pt.set_data(x[-1:], y[-1:])
        pt.set_3d_properties(z[-1:])
        # stick lines
        #stick_line.set_data(xx,zz)
        #stick_line.set_3d_properties(yy)
    ax.view_init(30, 0.3 * i)
    fig.canvas.draw()
    return lines + pts + stick_lines

# instantiate the animator.
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=500, interval=30, blit=True)

# Save as mp4. This requires mplayer or ffmpeg to be installed
#anim.save('lorentz_attractor.mp4', fps=15, extra_args=['-vcodec', 'libx264'])

plt.show()

因此​​,得出结论:我想,随着对点(橙色,黄色)和移动线(黄,绿)。如果有人能告诉我怎么做,我应该能够推断方法动画的其余部分。

So, to conclude: I would like lines that moves with the point pairs (orange, yellow) and (yellow, green). If someone could show me how to do that I should be able to extrapolate the methods to the rest of the animation.

一如以往,任何帮助是非常AP preciated。

As ever, any help is much appreciated.

原始数据可以在这里找到,如果有人想复制: https://开头www.dropbox.com/sh/80f8ue4ffa4067t/Pntl5-gUW4

The original data can be found here, if anyone wants to replicate: https://www.dropbox.com/sh/80f8ue4ffa4067t/Pntl5-gUW4

编辑:IMPLEMENTED SOLUTION

下面是最终的结果,使用所提出的解决方案。

Here is the final result, using the proposed solution.

推荐答案

我修改code以添加棒线,但简化了code,我删除了迹线:

I modified your code to add stick lines, but to simplify the code, I removed the trace lines:

import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('TkAgg') # Need to use in order to run on mac
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.colors import cnames
from matplotlib import animation

#=============================================================================================

t_start = 1917 # start frame
t_end = 2130 # end frame

data = pd.read_csv('Smart-first_phase_NaN-zeros.csv') # only coordinate data
df = data.loc[t_start:t_end,'Shoulder_left_x':'Ankle_right_z']

# Find max and min values for animation ranges
df_minmax = pd.DataFrame(index=list('xyz'),columns=range(2))
for i in list('xyz'):
    c_max = df.filter(regex='_{}'.format(i)).max().max()
    c_min = df.filter(regex='_{}'.format(i)).min().min()
    df_minmax.ix[i] = np.array([c_min,c_max])

df_minmax = 1.3*df_minmax # increase by 30% to make animation look better

df.columns  = np.repeat(range(12),3) # store cols like this for simplicity
N_tag = df.shape[1]/3 # nr of tags used (all)

N_trajectories = N_tag

t = np.linspace(0,data.Time[t_end],df.shape[0]) # pseudo time-vector for first walking activity
x_t = np.zeros(shape=(N_tag,df.shape[0],3)) # empty animation array (3D)

for tag in range(12):
    # store data in numpy 3D array: (tag,time-stamp,xyz-coordinates)
    x_t[tag,:,:] = df[tag]

x_t = x_t[:, :, [0, 2, 1]]

# Set up figure & 3D axis for animation
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1], projection='3d')
ax.axis('on')

# choose a different color for each trajectory
colors = plt.cm.jet(np.linspace(0, 1, N_trajectories))
# set up trajectory lines
lines = sum([ax.plot([], [], [], '-', c=c) for c in colors], [])
# set up points
pts = sum([ax.plot([], [], [], 'o', c=c) for c in colors], [])
# set up lines which create the stick figures

stick_defines = [
    (0, 1),
    (1, 2),
    (3, 4),
    (4, 5),
    (6, 7),
    (7, 8),
    (9, 10),
    (10, 11)
]

stick_lines = [ax.plot([], [], [], 'k-')[0] for _ in stick_defines]

# prepare the axes limits
ax.set_xlim(df_minmax.ix['x'].values)
ax.set_ylim(df_minmax.ix['z'].values) # note usage of z coordinate
ax.set_zlim(df_minmax.ix['y'].values) # note usage of y coordinate

# set point-of-view: specified by (altitude degrees, azimuth degrees)
ax.view_init(30, 0)

# initialization function: plot the background of each frame
def init():
    for line, pt in zip(lines, pts):
        # trajectory lines
        line.set_data([], [])
        line.set_3d_properties([])
        # points
        pt.set_data([], [])
        pt.set_3d_properties([])
    return lines + pts + stick_lines

# animation function.  This will be called sequentially with the frame number
def animate(i):
    # we'll step two time-steps per frame.  This leads to nice results.
    i = (5 * i) % x_t.shape[1]

    for line, pt, xi in zip(lines, pts, x_t):
        x, y, z = xi[:i].T # note ordering of points to line up with true exogenous registration (x,z,y)
        pt.set_data(x[-1:], y[-1:])
        pt.set_3d_properties(z[-1:])

    for stick_line, (sp, ep) in zip(stick_lines, stick_defines):
        stick_line._verts3d = x_t[[sp,ep], i, :].T.tolist()

    ax.view_init(30, 0.3 * i)
    fig.canvas.draw()
    return lines + pts + stick_lines

# instantiate the animator.
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=500, interval=30, blit=True)

plt.show()

下面是动画的一帧:

这篇关于3D动画与matplotlib,连接点来创建移动简笔画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆