Wygenerujemy prostą funkcję okresową i obejrzymy jej transformatę Fouriera. Później będziemy ją zaburzać
Funkcja np.random.random
generuje wartości z przedziału $[0,1]$. Żeby otrzymać wartości z zakresu $[-1,1]$ odejmujemy od każdej wartości 0,5 i mnożymy ją przez 2.
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import scipy
freq = 1 #Hz - liczba okresów na sekundę
amplitude = 3
time_to_plot = 100 # czas (długość danych wejściowych)
sample_rate = 20 # liczba próbek na sekundę
num_samples = sample_rate * time_to_plot
noise_amplitude = 0 # Zaczynamy od zerowych zaburzeń
noise = (np.random.random(num_samples) - 0.5) * 2
t = np.linspace(0, time_to_plot, num_samples)
sinus = [amplitude * np.sin(freq * i * 2*np.pi) for i in t]
signal = sinus + noise_amplitude * noise
Nasz sygnał wygląda tak:
plt.plot(t, signal);
fft_output = np.fft.rfft(signal)
magnitude_only = [np.sqrt(i.real**2 + i.imag**2)/len(fft_output) for i in fft_output]
frequencies = [(i*1.0/num_samples)*sample_rate for i in range(num_samples//2+1)]
plt.plot(frequencies, magnitude_only, 'r');
plt.plot(magnitude_only);
#plt.show()
Teraz zwiększamy amplitudę zaburzeń
noise_amplitude = 6
signal = sinus + noise_amplitude * noise
plt.plot(t, signal);
Na wykresie widać włąściwie tylko szum
fft_output = np.fft.rfft(signal)
magnitude_only = [np.sqrt(i.real**2 + i.imag**2)/len(fft_output) for i in fft_output]
frequencies = [(i*1.0/num_samples)*sample_rate for i in range(num_samples//2+1)]
plt.plot(frequencies, magnitude_only);
Mimo, że amplituda zaburzeń (6) jest dwukrotnie wyższa od amplitudy sygnału widać „pik” związany z częstością 1 Hz. Niestety, nie zawsze tak będzie
noise_amplitude = 14 # <---- cztery razy większa
signal = sinus + noise_amplitude * noise
fft_output = np.fft.rfft(signal)
magnitude_only = [np.sqrt(i.real**2 + i.imag**2)/len(fft_output) for i in fft_output]
frequencies = [(i*1.0/num_samples)*sample_rate for i in range(num_samples//2+1)]
plt.plot(frequencies, magnitude_only);
noise_amplitude = 15 # <---- pięć razy większa
signal = sinus + noise_amplitude * noise
fft_output = np.fft.rfft(signal)
magnitude_only = [np.sqrt(i.real**2 + i.imag**2)/len(fft_output) for i in fft_output]
frequencies = [(i*1.0/num_samples)*sample_rate for i in range(num_samples//2+1)]
plt.plot(frequencies, magnitude_only);
noise_amplitude = 18 # <---- sześć razy większa
signal = sinus + noise_amplitude * noise
fft_output = np.fft.rfft(signal)
magnitude_only = [np.sqrt(i.real**2 + i.imag**2)/len(fft_output) for i in fft_output]
frequencies = [(i*1.0/num_samples)*sample_rate for i in range(num_samples//2+1)]
plt.plot(frequencies, magnitude_only);
noise_amplitude = 24 # <---- osiem razy większa
signal = sinus + noise_amplitude * noise
fft_output = np.fft.rfft(signal)
magnitude_only = [np.sqrt(i.real**2 + i.imag**2)/len(fft_output) for i in fft_output]
frequencies = [(i*1.0/num_samples)*sample_rate for i in range(num_samples//2+1)]
plt.plot(frequencies, magnitude_only);
noise_amplitude = 30 # <---- osiem razy większa
signal = sinus + noise_amplitude * noise
fft_output = np.fft.rfft(signal)
magnitude_only = [np.sqrt(i.real**2 + i.imag**2)/len(fft_output) for i in fft_output]
frequencies = [(i*1.0/num_samples)*sample_rate for i in range(num_samples//2+1)]
plt.plot(frequencies, magnitude_only);
Zmniejszajac czas obserwacji sytuacja się pogarsza
freq = 1 #Hz - liczba okresów na sekundę
amplitude = 3
time_to_plot = 10 # czas (długość danych wejściowych) <--- !!!
sample_rate = 20 # liczba próbek na sekundę
num_samples = sample_rate * time_to_plot
noise_amplitude = 30
noise = (np.random.random(num_samples) - 0.5) * 2
t = np.linspace(0, time_to_plot, num_samples)
sinus = [amplitude * np.sin(freq * i * 2*np.pi) for i in t]
signal = sinus + noise_amplitude * noise
fft_output = np.fft.rfft(signal)
magnitude_only = [np.sqrt(i.real**2 + i.imag**2)/len(fft_output) for i in fft_output]
frequencies = [(i*1.0/num_samples)*sample_rate for i in range(num_samples//2+1)]
plt.plot(frequencies, magnitude_only, 'r');
Pik przy częstotliwości 1 widać, ale nie jest aż tak dominujący
freq = 1 #Hz - liczba okresów na sekundę
amplitude = 3
time_to_plot = 200 # czas (długość danych wejściowych) <--- !!!
sample_rate = 20 # liczba próbek na sekundę
num_samples = sample_rate * time_to_plot
noise_amplitude = 30
noise = (np.random.random(num_samples) - 0.5) * 2
t = np.linspace(0, time_to_plot, num_samples)
sinus = [amplitude * np.sin(freq * i * 2*np.pi) for i in t]
signal = sinus + noise_amplitude * noise
fft_output = np.fft.rfft(signal)
magnitude_only = [np.sqrt(i.real**2 + i.imag**2)/len(fft_output) for i in fft_output]
frequencies = [(i*1.0/num_samples)*sample_rate for i in range(num_samples//2+1)]
plt.plot(frequencies, magnitude_only, 'r');
Po zwiększeniu czasu obserwacji do 200 sekund — losowa struktura sygnału przebija się…