The component of the vector b along the line spanned by a is b^{\mathrm{T}} a / a^{\mathrm{T}} a.
A Fourier series is projecting f(x) onto \sin x. Its component p in this direction is exactly b_{1} \sin x.
Euler’s formula
The complex exponential e^{i x} is a combination of \cos x and \sin x:
e^{i x}=\cos x+i \sin x
So we can rewrite the Fourier series using complex exponentials:
f(x)=c_{0}+c_{1} e^{i x}+c_{2} e^{2 i x}+\cdots = \sum_k c_k\cdot e^{i k x}
pause
The formula for finding the coefficients c_{k} is the same as before, but now we use the complex exponential functions e^{i k x} instead of the sines and cosines:
We call the matrix F the DFT (Discrete Fourier Transform) matrix. It is a square unitary matrix of size N \times N.
The matrix F^\prime is the inverse DFT matrix. It is the complex conjugate of F divided by N.
Summary
The DFT can be written as a matrix-vector product \mathbf{y} = F \mathbf{c}.
The coefficients \mathbf{c} can be found by \mathbf{c} = F^\prime \mathbf{y}.
F is easy to compute, with a simple formula for each entry.
(There’s actually a really really fast way to compute the DFT using the FFT algorithm.)
Applications of the DFT
Filtering
The DFT is used in many applications, but one of the most common is filtering.
For example, suppose we have a signal that is a sum of two sinusoids:
f(x) = \sin(2\pi x) + 0.5 \sin(20\pi x)
What’s the DFT of this signal?
from scipy.fft import fft, fftshiftyf = fft(y)yfalone = fft(yalone)# make a non connected plot of yfplt.plot(np.fft.fftfreq(200),np.abs(yf), color='red')plt.plot(np.fft.fftfreq(200),np.abs(yfalone), color='blue')plt.xlim(-0.25, 0.25)plt.legend(['Full signal', 'low frequency only'])plt.show()
What’s with the double peaks?
Reconstruct the signal
We can reconstruct the signal by taking the inverse DFT.
Low-pass filtering
What if we just zero out the coefficient corresponding to the second sinusoid:
Try one more thing. Can we describe the change in the DFT as a multiplicative vector? We sure can.
So we can describe the new DVD as the old DFT multiplied by a vector of 1s and 0s.
The total process went like this:
Take the DFT of the signal.
Multiply the DFT by a vector of 1s and 0s to filter out the high frequency.
Take the inverse DFT to get the filtered signal.
Filtering as convolution
Suppose we have a signal and we’d like to try to filter out the high frequencies, but we don’t know which ones they are.
We could try with a simple filter like [1, 1, 1, 1, 1]/5. This is a simple moving average filter.
That means that we replace each point in the signal with the average of the 5 points before it.
Mathematically, this is:
f_{\text{filtered}}[n] = \sum_{m=0}^{4} f[n-m]/5
OK. We note that this can also be written as a convolution, between the signal and the vector h = [1, 1, 1, 1, 1, 0, 0, 0, ...]/5., where we have padded the vector with zeros so that it is the same length as the signal vector.
That is, h_0 = 1/5, h_1 = 1/5, h_2 = 1/5, h_3 = 1/5, h_4 = 1/5, and h_5 = 0, all the way to h_n=0.
Pad the filter with zeros to make it the same length as the signal.
Take the DFT of the filter.
Multiply the two DFTs.
Take the inverse DFT to get the filtered signal.
Done!
yf = fft(y)hf = fft(h, N) # pad h with zerosy_filtered = ifft(yf*hf)plt.plot(x, y, label='original')plt.plot(x, y_filtered, label='filtered')plt.legend()plt.show()
Then we can take the inverse DFT to get the filtered signal.