2016-12-07 2 views
0

Der Zweck des Programms: Ich muss eine Signalgrafik auf der Oberseite und eine Spektrum-Grafik dieses Signals auf der Unterseite, nur die y-Daten in beiden Fällen variieren.Wie zwei animierte Grafiken mit x-Achse in Matplotlib mit Unterplotts plotten?

Ich erzeuge eine Sinuswelle mit einem zufälligen Rauschen auf dem Eingang und zeichne es auf der Oberseite, das funktioniert perfekt.

Das Problem ist, wenn ich versuche, das Spektrumsdiagramm zu plotten. Es wird aus irgendeinem Grund nicht aktualisiert und ich habe die Funktionsweise von matplotlib.animation.FuncAnimation nicht sehr gut verstanden.

Der Code:

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 

Bonus: Wie initialisieren ich Daten und Größe richtig?

Antwort

0

Damit sowohl die Zeit- als auch die Häufigkeitsgrafik aktualisiert werden kann, müssen Sie die Daten von beiden auf die entsprechenden Diagramme in der update-Funktion einstellen. Natürlich müssen Sie diese Daten auch in der generierenden Funktion angeben. Also sollte die generierende Funktion yield (data, magnitude) und die Aktualisierungsfunktion dieses Tupel als Eingabe akzeptieren.

Es ist auch eine gute Idee, einige Grenzwerte für das Frequenzdiagramm freqGraph.set_ylim([0, 0.006]) so festzulegen, dass es nicht leer bleibt.

Ich weiß nicht, was Sie unter verstehen Wie initialisiere ich Daten und Magnitude korrekt?. Ich denke, dass sie korrekt in dem Sinne initialisiert werden, dass sie für jeden Frame einschließlich des allerersten berechnet werden.

Hier ist ein Arbeitscode.

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 
+0

Vielen Dank! Ich war etwas verwirrt darüber, wie "matplotlib.animationFuncAnimation()" funktioniert. –

+0

Löst diese Antwort Ihr Problem? Wenn ja, können Sie es akzeptieren. Wenn nicht, oder wenn Sie auf weitere/bessere Antworten warten, können Sie Ihre Frage mit verfeinerten Anforderungen aktualisieren, so dass die Leute wissen, wonach Sie suchen. – ImportanceOfBeingErnest

+0

Sry, ich wusste nicht darüber: D Akzeptiert. –

Verwandte Themen