如何在matplotlib中使用子图修剪2个x轴的动画图形?

时间:2016-12-07 04:09:37

标签: python animation matplotlib plot fft

程序的目的:我需要在顶部绘制一个信号图形,在底部绘制该信号的光谱图,只有两种情况下的y数据都有所不同。

我在输入上生成一个带有随机噪声的正弦波,并将其绘制在顶部,这样可以正常工作。

问题在于我尝试绘制频谱图。由于某些原因它没有更新,我不太了解matplotlib.animation.FuncAnimation的功能。

代码:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

dt = 0.01
Fs = 44000.0              # sample rate
timestep = 1.0/Fs         # sample spacing (1/sample rate)
t = np.arange(0, 10, dt)  # t range
n = 256                   # size of the array data
w = 10000                 # frequency of the input

data = np.sin(2*np.pi*w*t)



def update(data):
    # update the curves with the incoming data
    line.set_ydata(data)
    #line2.set_ydata(magnitude)

    return line,

def generateData():
    # simulate new data coming in
    while True:
        nse = np.random.randn(len(t))
        r = np.exp(-t/0.05)
        cnse = np.convolve(nse, r)*dt
        cnse = cnse[:len(t)]
        data =  np.sin(2*np.pi*w*(t)) + cnse
        magnitude = np.fft.fft(data)/n
        magnitude = np.abs(magnitude[range(n//2)])
        yield data

fig = plt.figure()

# plot time graph axis
timeGraph = plt.subplot(2, 1, 1)
timeGraph.set_ylim(-0.2, 0.2)
timeGraph.set_xlabel('Time')
timeGraph.set_ylabel('Amplitude')

# plot frequency graph axis
freqGraph = plt.subplot(2, 1, 2)
freqGraph.set_xlabel('Freq (Hz)')
freqGraph.set_ylabel('|Y(freq)|')

# get frequency range
n = len(data) # length of the signal
print(len(data))
k = np.arange(n)
T = n/Fs
freq = k/T # two sides frequency range
freq = freq[range(n//2)] # one side frequency range

# fft computing and normalization
magnitude = np.fft.fft(data)/n
magnitude = np.abs(magnitude[range(n//2)])


line, = timeGraph.plot(np.linspace(0, 1, len(t)), 'b')
line2, = freqGraph.plot(freq, magnitude, 'g')


# animate the curves
ani = animation.FuncAnimation(fig, update, generateData,
                              interval=10, blit=True)

plt.show() # open window

额外奖励:如何正确初始化数据和数量?

1 个答案:

答案 0 :(得分:0)

为了更新时间和频率图,您需要将数据从两者都设置为update函数中的相应图。当然,您还需要在生成函数中提供此数据。因此生成函数应yield (data, magnitude),更新函数应接受此元组作为输入。

为频率图freqGraph.set_ylim([0, 0.006])设置一些限制也是一个好主意,这样它就不会保持为空。

我不知道你是什么意思如何正确初始化数据和幅度?。我认为它们是正确初始化的,因为它们是针对每一帧计算的,包括第一帧。

这是一个有效的代码。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

dt = 0.01
Fs = 44000.0              # sample rate
timestep = 1.0/Fs         # sample spacing (1/sample rate)
t = np.arange(0, 10, dt)  # t range
n = 256                   # size of the array data
w = 10000                 # frequency of the input

data = np.sin(2*np.pi*w*t)



def update(data):
    # update the curves with the incoming data
    line.set_ydata(data[0])
    line2.set_ydata(data[1])
    return line, line2,

def generateData():
    # simulate new data coming in
    while True:
        nse = np.random.randn(len(t))
        r = np.exp(-t/0.05)
        cnse = np.convolve(nse, r)*dt
        cnse = cnse[:len(t)]
        data =  np.sin(2*np.pi*w*(t)) + cnse
        magnitude = np.fft.fft(data)/n
        magnitude = np.abs(magnitude[range(n//2)])
        yield (data, magnitude)

fig = plt.figure()

# plot time graph axis
timeGraph = plt.subplot(2, 1, 1)
timeGraph.set_ylim(-0.2, 0.2)
timeGraph.set_xlabel('Time')
timeGraph.set_ylabel('Amplitude')

# plot frequency graph axis
freqGraph = plt.subplot(2, 1, 2)
freqGraph.set_ylim([0, 0.006])
freqGraph.set_xlabel('Freq (Hz)')
freqGraph.set_ylabel('|Y(freq)|')

# get frequency range
n = len(data) # length of the signal
print(len(data))
k = np.arange(n)
T = n/Fs
freq = k/T # two sides frequency range
freq = freq[range(n//2)] # one side frequency range

# fft computing and normalization
magnitude = np.fft.fft(data)/n
magnitude = np.abs(magnitude[range(n//2)])


line, = timeGraph.plot(np.linspace(0, 1, len(t)),'b')
line2, = freqGraph.plot(freq, magnitude,'g')


# animate the curves
ani = animation.FuncAnimation(fig, update, generateData,
                              interval = 10, blit=True)

plt.show() # open window