如何使用 matplotlib FuncAnimation 显示 numpy 数组的滑动 windows

How to show sliding windows of a numpy array with matplotlib FuncAnimation

我正在开发一种用于检测信号峰值的简单算法。为了对我的算法进行故障排除(并展示它),我想在整个信号持续时间内观察信号和检测到的峰值(即 100Hz = 20000 时间点的 20 分钟).

我认为最好的方法是创建一个带有 matplotlib.animation.FuncAnimation 的动画图,它将连续显示信号滑动 1 个时间点及其在一段时间内的叠加峰值 windows 5 秒(即 500 时间点)。信号存储在一维 numpy.ndarray 中,而峰信息存储在二维 numpy.ndarray 中,包含峰的 xy 坐标。

这是情节的“静止画面”。

现在的问题是我无法完全理解使用 FuncAnimation 执行此操作的方式。

如果我的理解是正确的,我需要三个主要部分:init_func 参数,一个创建绘制绘图的空框的函数,func 参数,即函数实际上为每个帧创建图,以及在帮助中定义为 Source of data to pass func and each frame of the animation.

的参数 frames

查看带有 FuncAnimation 的绘图示例,我只能找到其中要绘制的数据是在移动中创建的用例,例如 here, or here,其中要绘制的数据是 frame.

的基础上创建

我不明白的是如何使用已经存在的数据来实现这一点,但这些数据是在框架的基础上 切片 的。因此,我需要 frame 作为一种滑动 window,其中第一个 window 从 0499,第二个从 1500 等等,直到 ndarray 中的时间点结束,以及关联的 func 将 select 点绘制在frames 的基础。我不知道如何实现这个。

我添加代码来创建一个真实的信号,简单地检测峰值并绘制我想要制作动画的 'static' 版本的绘图:

import neurokit2 as nk
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
from scipy.signal import find_peaks
#create realistic data
data = nk.ecg_simulate(duration = 50, sampling_rate = 100, noise = 0.05,\
                       random_state = 1)
#scale data
scaler = MinMaxScaler()
scaled_arr = scaler.fit_transform(data.reshape(-1,1))
#find peaks
peak = find_peaks(scaled_arr.squeeze(), height = .66,\
        distance = 60, prominence = .5)
#plot
plt.plot(scaled_arr[0:500])
plt.scatter(peak[0][peak[0] < 500],\
         peak[1]['peak_heights'][peak[0] < 500],\
             color = 'red')

我已经使用您提供的数据创建了一个动画;我已经为 5000 个数据提取了 500 个增量的数据并更新了图表。为了便于提取数据,我创建了一个 500 行的索引,其中 id[0] 是开始行,id1 是结束行,帧数是 10。这段代码有效,但是初始设置和数据集在散点图中不起作用,所以我在循环过程中直接绘制了散点图。

import neurokit2 as nk
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from scipy.signal import find_peaks
import numpy as np

#create realistic data
data = nk.ecg_simulate(duration = 50, sampling_rate = 100, noise = 0.05, random_state = 1)

#scale data
scaler = MinMaxScaler()
scaled_arr = scaler.fit_transform(data.reshape(-1,1))
#find peaks
peak = find_peaks(scaled_arr.squeeze(), height = .66, distance = 60, prominence = .5)

ymin, ymax = min(scaled_arr), max(scaled_arr)
fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot([],[], lw=2)
scat = ax.scatter([], [], s=20, facecolor='red')

idx = [(s,e) for s,e in zip(np.arange(0,len(scaled_arr), 1), np.arange(499,len(scaled_arr)+1, 1))]

def init():
    line.set_data([], []) 
    return line, 

def animate(i):
  id = idx[i]
  #print(id[0], id[1])
  line.set_data(np.arange(id[0], id[1]), scaled_arr[id[0]:id[1]])
  x = peak[0][(peak[0] > id[0]) & (peak[0] < id[1])]
  y = peak[1]['peak_heights'][(peak[0] > id[0]) & (peak[0] < id[1])]
  #scat.set_offsets(x, y)
  ax.scatter(x, y, s=20, c='red')
  ax.set_xlim(id[0], id[1])
  ax.set_ylim(ymin, ymax)
  return line,scat

anim = FuncAnimation(fig, animate, init_func=init, frames=50, interval=50, blit=True) 

plt.show()

可能不是您想要的,希望对您有所帮助,

import neurokit2 as nk
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from sklearn.preprocessing import MinMaxScaler
import numpy as np
from matplotlib.animation import FuncAnimation


fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

# This function is called periodically from FuncAnimation
def animate(i, xs, ys):

    xs = xs[i]
    ys = ys[i]

    # Draw x and y lists
    ax.clear()
    ax.plot(xs, ys)

if __name__=="__main__":
   
  data = nk.ecg_simulate(duration = 50, sampling_rate = 100, noise = 0.05, random_state = 1)
  scaler = MinMaxScaler()
  scaled_arr = scaler.fit_transform(data.reshape(-1,1))
  
  ys = scaled_arr.flatten()
  ys = [ys[0:50*i] for i in range(1, int(len(ys)/50)+1)]
  xs = [np.arange(0, len(ii)) for ii in ys ]
  
 
  ani = animation.FuncAnimation(fig, animate, fargs=(xs, ys), interval=500)
  ani.save('test.gif')