A Glimpse of Fourier Theory

Joshua R. Davis, jdavis@carleton.edu, 2022 February 7

This Mathematica notebook is intended to give you a glimpse of what the Fourier transform means. You are not expected to understand or practice any of the following computations, and you are not expected to learn Mathematica. Rather, you are just supposed to run the code, examine the plots, and read the commentary. I hope that you will come away thinking, “If I was researching a problem that involved some kind of periodic phenomenon, it would be reasonable to try Fourier theory on it.”

To use this notebook, open it in Mathematica. As you read, activate each chunk of code by clicking on it and then pressing Enter (or Shift-Return). Most of the code chunks generate pictures.

Taylor Series

Let f(t) = sin(t) / t. This function is also known as sinc(t). Its graph is like a cosine wave that gets smaller in amplitude as t moves away from t = 0.

Clear[t];
fOfT = Sinc[t];
Plot[fOfT, {t, -20, 20}, PlotRange->{-0.5, 1.5}]

As you might have learned in calculus, a Taylor series is a way of writing f(t) as an infinite linear combination of powers of t. For practical reasons, we often truncate the Taylor series to get what’s called a Taylor polynomial. It is an approximation to f(t). Roughly speaking, the approximation gets better as we include more terms of the Taylor series.

fOfTApprox = 1 / 1!
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = 1 / 1! - t^2 / 3!
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = 1 / 1! - t^2 / 3! + t^4 / 5!
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = 1 / 1! - t^2 / 3! + t^4 / 5! - t^6 / 7!
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = 1 / 1! - t^2 / 3! + t^4 / 5! - t^6 / 7! + t^8 / 9!
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = 1 / 1! - t^2 / 3! + t^4 / 5! - t^6 / 7! + t^8 / 9! - t^10 / 11!
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = 1 / 1! - t^2 / 3! + t^4 / 5! - t^6 / 7! + t^8 / 9! - t^10 / 11! + t^12 / 13!
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]

Notice that the Taylor polynomials tend to approximate f(t) extremely well near t = 0 and extremely poorly as t moves away from t = 0. It turns out that Taylor series and Taylor polynomials are just one approach to expressing a function f(t) as an infinite linear combination of simpler functions. Other approaches have different convergence properties and hence different theoretical and practical purposes.

Fourier Series

Another important approach is the Fourier series. While the Taylor series is based on the functions 1, t, t^2, t^3, ..., the Fourier series is based on the functions e^(i k t) = cos t + i sin t. Here’s the same f(t) = (sin t) / t example as above, with its first few Fourier approximations. (This next code cell might take a couple of minutes to complete its execution.)

Clear[t];
fOfT = Sinc[t];
fOfTApprox = FourierSeries[fOfT, t, 0, FourierParameters->{1, Pi / 20}]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = FourierSeries[fOfT, t, 1, FourierParameters->{1, Pi / 20}]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = FourierSeries[fOfT, t, 2, FourierParameters->{1, Pi / 20}]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = FourierSeries[fOfT, t, 3, FourierParameters->{1, Pi / 20}]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = FourierSeries[fOfT, t, 4, FourierParameters->{1, Pi / 20}]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = FourierSeries[fOfT, t, 5, FourierParameters->{1, Pi / 20}]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]
fOfTApprox = FourierSeries[fOfT, t, 6, FourierParameters->{1, Pi / 20}]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-0.5, 1.5}]

As you can see, the Fourier approximation is better than the Taylor approximation in some ways and worse in other ways. The Fourier approximation seems more aware that f(t) is wavy. That’s not surprising, because the Fourier approximation is built out of sine and cosine functions. To drive the point home, here’s an even simpler example, for which the Fourier series exactly captures the function after just a few terms.

Clear[t];
fOfT = Sin[t] + Sin[3 t]
Plot[fOfT, {t, -20, 20}, PlotRange->{-2, 2}]
fOfTApprox = FourierSeries[fOfT, t, 0]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-2, 2}]
fOfTApprox = FourierSeries[fOfT, t, 1]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-2, 2}]
fOfTApprox = FourierSeries[fOfT, t, 2]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-2, 2}]
fOfTApprox = FourierSeries[fOfT, t, 3]
Plot[{fOfT, fOfTApprox}, {t, -20, 20}, PlotRange->{-2, 2}]

Fourier Transform

The Fourier transform of the function f(t) is a function fHat(w) defined by 

    fHat(w) = (1/(Sqrt[2 π]))(∫_(-∞)^∞)f(t)(e^(i w t))dt.

(Actually there are several slightly different conventions. Some people insert a minus sign before the i. Some people use a different constant in front of the integral.) All I want you to know about it is: For each frequency w, fHat(w) tells us how much the frequency w is represented in the Fourier expansion of f. To understand this difficult concept, let’s start with simple examples.

Clear[t];
fOfT = Sin[t]
Plot[fOfT, {t, -20, 20}, PlotRange->{-2, 2}]
fHatOfW = FourierTransform[fOfT,t, w]
Plot[Abs[fHatOfW ], {w, -4, 4}, PlotRange->Full]

Here’s how to decode those responses from Mathematica. The Dirac delta function is (at least intuitively) a function that has a very tall, very narrow spike at 0. So the graph above should show spikes at -1 and 1. It should really look something like this...

Plot[
PDF[NormalDistribution[-1, 0.01], w] +PDF[NormalDistribution[1, 0.01], w], 
{w, -4, 4}, PlotRange->Full]

...except that the spikes should be much taller and much narrower. These spikes indicate that the function f(t) is made up of (sines and cosines with) frequency 1, and that there are no other frequencies present in f(t). Does that make some intuitive sense?

Now here’s another example consisting of frequencies 1 and 3.

Clear[t];
fOfT = Sin[t] + Sin[3 t]
Plot[fOfT, {t, -20, 20}, PlotRange->{-2, 2}]
fHatOfW = FourierTransform[fOfT,t, w]
Plot[Abs[fHatOfW ], {w, -4, 4}, PlotRange->Full]
Plot[
PDF[NormalDistribution[-3, 0.01], w] + PDF[NormalDistribution[-1, 0.01], w] +PDF[NormalDistribution[1, 0.01], w] + PDF[NormalDistribution[3, 0.01], w], 
{w, -4, 4}, PlotRange->Full]

This example is only slightly different. Find the differences.

Clear[t];
fOfT = Sin[t] + Cos[3 t]
Plot[fOfT, {t, -20, 20}, PlotRange->{-2, 2}]
fHatOfW = FourierTransform[fOfT,t, w]
Plot[Abs[fHatOfW ], {w, -4, 4}, PlotRange->Full]
Plot[
PDF[NormalDistribution[-3, 0.01], w] + PDF[NormalDistribution[-1, 0.01], w] +PDF[NormalDistribution[1, 0.01], w] + PDF[NormalDistribution[3, 0.01], w], 
{w, -4, 4}, PlotRange->Full]

Finally, let’s revisit our first example. Its frequency content is much more interesting. It contains all frequencies between -1 and 1 and no frequencies other than those.

Clear[t];
fOfT = Sinc[t];
Plot[fOfT, {t, -20, 20}, PlotRange->{-2, 2}]
fHatOfW = FourierTransform[fOfT, t, w]
Plot[fHatOfW, {w, -4, 4}]

Discrete Fourier Transform

If we’re going to use Fourier theory to analyze a signal (e.g. a sound wave or raster image) on a computer, then we need a version of the Fourier transform that is discrete rather than continuous. It’s called the discrete Fourier transform. It takes as input an array of (2^n) complex numbers, and returns as output an array of (2^n) complex numbers that characterize the frequency content of the input. In the following example, there are two frequencies.

Clear[t];
fOfT = Cos[t] + Sin[10 t];
ts = Table[t0, {t0, 0, 127, 1}];
fOfTs = Table[fOfT /. t -> t0, {t0, 0, 127, 1}];
ListLinePlot[fOfTs]

The two frequencies show up as two peaks in the following plot. (There are also two other peaks, which are mirror images of the first two.)

ListLinePlot[Abs[Fourier[fOfTs]], PlotRange -> Full]