In [1]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_context("talk")
In [2]:
f_s = 50.0 # Hz
f = 1.0 # Hz
time = np.arange(0.0, 3.0, 1/f_s)
x = 5 * np.sin(2 * np.pi * f * time) + 2 * np.sin(10 * 2 * np.pi * f * time)
In [3]:
plt.plot(time, x)
plt.xlabel("Time (sec)")
plt.ylabel("x")
Out[3]:
In [4]:
fft_x = np.fft.fft(x)
n = len(fft_x)
freq = np.fft.fftfreq(n, 1/f_s)
print n
print freq
In [5]:
plt.plot(np.abs(fft_x))
Out[5]:
In [6]:
fft_x_shifted = np.fft.fftshift(fft_x)
freq_shifted = np.fft.fftshift(freq)
In [7]:
plt.plot(freq_shifted, np.abs(fft_x_shifted))
plt.xlabel("Frequency (Hz)")
Out[7]:
It's actually more common to look at just the first half of the unshifted FFT and frequency vectors and fold all the amplitude information into the positive frequencies. Furthermore, to get ampltude right, we must normalize by the length of the original FFT. Note the factor of $2/n$ in the following which accomplishes both the folding and scaling.
In [8]:
half_n = np.ceil(n/2.0)
fft_x_half = (2.0 / n) * fft_x[:half_n]
freq_half = freq[:half_n]
In [9]:
plt.plot(freq_half, np.abs(fft_x_half))
plt.xlabel("Frequency (Hz)")
plt.ylabel("Amplitude")
Out[9]:
Now the spectrum contains spikes at the correct amplitudes at only positive frequencies, which are the only ones with physicality.