A Primer On Fourier Analysis - Part I
A Primer On Fourier Analysis - Part I
LabKitty
Browlf
claim if you understand that, then you understand Fourier analysis. Alas, crux moves (11)
drink and derive (13)
that goal will require a number of concepts that have more to do with eigenvalues (8)
computational details than underlying ideas. Those details take something evil thesis advisor (6)
simple and beautiful and make it seem harder and uglier than it really is. famous first words (16)
fear and loathing (6)
funding (10)
As such, I have broken the Primer into two parts. In Part I, we meet the
git (4)
Fourier transform. What it is, what it means, how to calculate it if you don't happy math (7)
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 1/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
care about computational efficiency, and why it's so dang useful. We'll also javascript (22)
LabKitty Academy (10)
take a look at the equations to help connect my presentation to what you'll
LabKitty apps (5)
find in textbooks. In Part II, we'll get into how the pros do it. What a Nyquist LabKitty primer (8)
frequency is, why there's only N/2 Fourier coefficients for a signal with N LabKitty reads (7)
samples, what a power spectral density is, why it should have error bars, LabKitty recommends (24)
LabKitty watches stuff (11)
and so on. Answers to those questions are not beyond the mortal ken, but
mad scientist (20)
you should have a firm grasp of what Fourier is doing before you take a matlab (8)
look under his hood, so to speak. Ergo, Part II. neurobrowlf (13)
now this (16)
politics (19)
My emphasis throughout is how the technique is used in computational
quote monstah (16)
applications, particularly in digital signal processing. If you're looking for
sanity check (13)
existence and uniqueness proofs or Parsevel's theorem or contour shameless self-promotion (9)
integration or Dirichlet conditions, you need to look elsewhere. But if you've shop talk (11)
ever wondered just what the heck Fourier was ranting about, read on. win stuff (3)
We start simple. Consider the following: We have two sine waves. For now,
let's make the frequency of one an integer multiple of the other. So 1 Hz
and (a smaller amplitude) 8 Hz will do, When plotted over a period of one
second, they look like this:
If we add these two sine waves together, we get the following composite
waveform:
The idea of Fourier analysis is this: Can we go in the other direction? That
is, given a function,* can we extract the collection of sine waves that
generates it? That's it. That's the concept in a nutshell.
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 2/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
Footnote: You may have noticed the time axis in the above plots goes from
0 to 100 and not 0 to 1. This is because I plotted amplitude versus sample
number and 100 is the number of samples I used to generate the
waveforms (I'll show code in a just a bit). I could have relabeled the time
axis to go 0 to 1, but sometimes it's useful to see how many samples are in
the waveform at a glance, and relabeling would hide that information. If this
bugs you, imagine the abscissa labeled time in 1/100ths of a second.
If all this seems trivial, note we will quickly segue from the "what" to the
"how" and figuring out how to extract the sinusoidal components of a
function took humans quite awhile to grok. Fourier only announced his
technique in 1807, which is many years ago but it's more than a century
after Newton invented calculus. The concept of the Fourier transform
eluded many smart people for a very long time indeed.
tmax = 1;
t = [0.01:0.01:tmax];
N = length(t);
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 3/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
x = sin(1*2*pi*t) + 0.25*sin(8*2*pi*t);
nc = 10;
components = zeros(nc,1);
% reconstruction of x
rx = zeros(size(x));
scale = 2/N;
clf;
subplot(3,1,1);
plot(x);
axis([1 100 -1.2*max(x) 1.2*max(x)]);
a = axis;grid on;
subplot(3,1,2);
bar(components,'k');
axis([0 nc -1 1.2*max(components)]);
subplot(3,1,3);
plot(rx,'r');
axis(a);grid on;
Enough code; let's see some results. Here's the Fourier decomposition of
our 1 Hz + 8 Hz signal:
The trace in the top panel is the original signal. The middle panel is a bar
plot of the amplitude of the sine wave present at each frequency, which I'm
going to call the Fourier coefficients. Furthermore, I will refer to this result
as performing a Fourier decomposition. The Fourier coefficients collectively
define the signal's frequency domain representation, in contrast to the time
domain representation we started with. The red trace at bottom is a
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 4/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
reconstruction of the data using the Fourier components (handy mnemonic:
red for "reconstruction").
So far, so good. I'll mention two caveats, and then I'll introduce a few
hiccups that require modification of our algorithm.
First, we are working here with sampled data (aka discrete data). That is, I
generated the two waveforms by sampling a 1 Hz and 8 Hz sine wave at a
finite number of places (100 places, to be specific). The waveforms look
like continuous functions but that's only because I'm "connecting the dots"
in the plots so to speak. This is so common when plotting data you
probably don't even think about it. However, there are important differences
when doing Fourier analysis of sampled data (i.e., in Matlab or Octave)
compared to Fourier analysis of continuous functions (i.e., pencil-and-
paper type calculations). We'll bump into these differences a little later.
Second, I made up the data in this example so I knew what sine waves
were present. As such, I knew when to stop correlating. However, suppose
we were given an arbitrary waveform to decompose. How would we know
when we have extracted all possible components? Surprisingly, this
seemingly-innocent question opens a monster can of worms. The short
answer is for data of length N, you can extract at most N/2 components.
(Our data was 100 samples, so we cannot extract more than 50 sine
waves.) Why the maximum is N/2 and not some sensible number like N (or
infinity) will be explained in Part II. Also, while I would be technically
justified in showing all N/2 components in the bar plot, I only showed the
first dozen or so otherwise the bars get scrunched together. I knew what
frequencies were present, so plotting a bunch of zero components seemed
silly.
Let's try it. Change the definition of x(t) to a 5 Hz sine wave in the code:
x = sin(5*2*pi*t);
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 5/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
Cool. It works. Now let's try our algorithm on a 5 Hz sine wave that includes
a constant term that shifts the signal away from zero (this is called a DC
offset):
x = sin(5*2*pi*t) + 1.0;
Hmm. That's not so good. Our algorithm still extracts the proper coefficient,
but the reconstruction is wrong -- it fails to include the offset. The good
news is that's easy enough to fix: We simply remove any DC before
performing the decomposition (this is called demeaning the data) and we
add that offset back at the end when we reconstruct the data. Bullet
dodged.
x = sin(5*2*pi*(t-0.25);
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 6/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
tmax = 1; % must be 1
t = [0.01:0.01:tmax];
N = length(t);
x = sin(5*2*pi*t);
% x = x + 0.4* sin(15*2*pi*t);
% x = sin(5*2*pi*(t-0.25));
% x = x + 1;
dc = mean(x);
dmx = x - dc;
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 7/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
nc = N/2;
bk = zeros(nc,1);
ak = zeros(nc,1);
for k = 1:nc
temp = sin(k*2*pi*t);
bk(k) = dot(temp,dmx);
temp = cos(k*2*pi*t);
ak(k) = dot(temp,dmx);
end
% reconstruction of x
rx = zeros(size(x));
scale = 2/N;
for k = 1:nc
temp = scale * cos(k*2*pi*t);
rx = rx + ak(k) * temp;
temp = scale * sin(k*2*pi*t);
rx = rx + bk(k) * temp;
end
rx = rx + dc;
subplot(3,1,1);
plot(x);
axis([1 N -2 2]);
a = axis; grid on;
subplot(3,1,2);
power_spectral_density = (bk.^2+ak.^2)/N;
bar(power_spectral_density,'k');
axis([0 nc -0.1 1.2*max(power_spectral_density)]);
subplot(3,1,3);
plot(rx,'r');
axis(a); grid on;
The reconstruction from the new algorithm matches the data. Note I'm now
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 8/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
bar-plotting the sum of the squares of the sine and cosine coefficients at
each frequency (divided by N) rather than their individual amplitudes. I'm
also now plotting all N/2 of these, as is standard practice. This quantity is
called power and this kind of a plot is called a power spectral density. We
will have much more to say about the PSD in Part II.
Footnote: I'm using the variable names ak and bk for the vector of sine and
cosine coefficients in the code. These are standard names used in the
textbooks. We shall bump into them a bit later.
Ack! The reconstruction is now twice the amplitude of the original data!
Also, the Fourier components appear to be repeating. There's correct
components at 5 Hz and 15 Hz, but then two ghosts appear at 85 Hz and
95 Hz! What is going on??
It's no coincidence that the data is twice is long and the results are 2x as
wrong. (Indeed, tripling the length of the data produces six components
and a reconstruction 3x the correct amplitude.) The short answer is it's not
the number of samples (divided by 2) that determines the number of
frequencies we can extract, it's the number of samples per unit time
(divided by 2). In signal processing lingo, this is called the sampling
frequency. One thousand samples per second is aka a sampling frequency
of 1 KHz and we can extract 500 components. Forty samples per second is
aka a sampling frequency of 40 Hz and we can extract 20 components.
And so on. We have been using 100 samples per second in the examples,
so we can extract 50 components. However, changing tmax to 2 increased
the length of N to 200, and the code tried to extract 100, not 50. Half of
these components are ghosts and including the ghosts broke the
reconstruction.
We'll see how to fix this properly in Part II. For now, I just make a note in
the code that tmax must be 1. Again, you can run the code yourself and
verify we get the correct result.
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 9/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
That's it. That is truly the concept of the Fourier transform a nutshell. All
that's left is improving computational efficiency and chasing around the
theoretical implications. As I promised in the introduction, I will not get into
these topics. However, I should at least show you some equations because
that will help you connect my explanation to a proper treatment you will find
in textbooks and elsewhere. Additionally, I have thus-far been rather
cavalier with my terminology which is no doubt offending the purists.
Showing some equations will provide me an opportunity to define things
more carefully.
A purist would point out what I have been calling the Fourier transform
should really have been called the Discrete Fourier Transform (DFT) which
is more like a Fourier series and less like a Fourier transform. A purist
would also make a distinction between the Discrete Fourier Transform and
the Discrete Time Fourier Transform (DTFT), and then note the Fast
Fourier Transform (FFT) is just an efficient way of computing the DFT. A
purist might then start to drone on about Fourier transforms on arbitrary
locally compact abelian topological groups, and whoever put that on the
Fourier transform Wikipedia page needs to be slapped. There's a
difference between "helpful" and "showing off," which is something a purist
doesn't understand.
You are forgiven if you find this zoo of terminology confusing. Let's see if
we can't organize the various Fourier animals into their proper cages.
Those cages go as follows:
I've included the type of function each method can analyze in parentheses.
Just to be clear, when I say "continuous" I mean pencil-and-paper kind of
solutions. In Matlab or Octave (or any software) we work with "discrete"
data, aka "sampled" data, aka "digital" data, aka a "sequence." (Also, just
to be clear, I use the terms "data" and "waveform" and "signal" and
"function" and "input" interchangeably.) Keep in mind any equation I show
might be written slightly differently in your textbook or in other sources.
Stay frosty.
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 10/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
write that special value T0 and call it the fundamental period. Sometimes
it's more useful to talk about frequency than period, so we define f0 = 1/T0
which is called the fundamental frequency. Frequency tends to get
multiplied by 2π in the equations, so we define the fundamental angular
frequency ω0 = 2πf0 so we don't have to keep writing 2π everywhere. The
units of f0 are cycles-per-second (aka "Hertz"); the units of ω0 are radians-
per-second (aka "radians-per-second").
With terminology and notation in hand, we can basically just write down an
equation analogous to the rock-stupid algorithm for Fourier decomposition
we used earlier:
x(t) = a0/2 +
Σk=1,∞ [ ak ⋅ cos(kω0t) + bk ⋅ sin(kω0t) ]
This is the trigonometric form. The leading coefficient a0/2 is the DC offset
(if present), to which is added sine and cosine components having
multiplies of the fundamental frequency (some authors just write a0 and
absorb the factor of 1/2 in the coefficient definition). Earlier I noted we can
extract a maximum of N/2 components from data containing N samples.
That limit does not apply for a continuous function, which is why the sum
here goes to infinity.
The integral is over one period. Interestingly, it doesn't matter where you
begin and end, as long as you integrate over one complete period.
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 11/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
think. See any textbook on Fourier analysis for details.
Note the new summation limits (−∞ ,∞). The constants Ck are given by:
Footnote: Although you're free to work with whichever pair you like, I
beseech thee to pick the complex exponential form as your favorite even
though it might seem unnecessarily complicated. The sooner you become
comfortable with complex exponentials, the easier your life will become,
not just in Fourier analysis but in all areas of mathematics.
Here, somebody will haughtily sniff and tell you a negative frequency is
obviously the same thing as a positive frequency except the signal is
moving backwards in time. Hey, thanks a million Wikipedia. You're a peach.
From now on, when you see a complex exponential, practice shrugging
and saying: Meh, little arrow spinning around in the complex plane. The
relation of the phasor to the familiar (i.e., real-valued) trigonometric
functions are generated by its projections on the real and imaginary axes
(shown here in red and blue). As the phasor moves around the circle, its
shadow on the real axis sweeps out a cosine (red) and its shadow on the
imaginary axis sweeps out a sinewave (blue). The speed of the spinning is
determined by the frequency, ω (bigger = faster). If the frequency is
positive, the arrow moves counterclockwise (convince yourself of this by
substituting a few values of t).
If the frequency is negative, the arrow moves clockwise. That's it. That's all
a "negative frequency" is.
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 13/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
approximately the area under f(x) between a and b. In the limit as N goes
to infinity, the Riemann sum defines the integral ∫a,b f(x) dx and is exactly
the area under f(x) between a and b. Go look up the Riemann sum (or at
least draw a picture) if you are shaky on the concept.
Suppose x(t) is a non-periodic function. Suppose also that x(t) is finite, that
is, x(t) = 0 for | t | > τ for some number τ (we'll let τ go to infinity eventually,
so this isn't a serious restriction. Also, τ is supposed to be the Greek letter
tau; I've noticed in some browsers it looks like a miniature T. FYI).
Now, form a periodic extension of x(t) by cutting and pasting copies of x(t)
to the left and right of itself forever (be sure to include a little zero padding
between copies). Here's an example of what I mean:
Let's call the periodic extension xP(t). Note xP(t) is periodic. Ergo, xP(t) has
a Fourier series:
We can evaluate the integral anywhere we like, so long as its over one full
period. Let's use −T0/2 to +T0/2 (we assume there's sufficient zero padding
such that −T0/2 < −τ and τ < T0/2). Inside [−T0/2 T0/2 ], xP(t) is x(t) plus a
bunch of zero-padding that doesn't contribute anything to an integral. So
we can write:
(Note x(t) is back in the integrand). Outside [−τ τ], x(t) = 0. So we can
extend the integral limits:
I'll explain why we do this in a moment. For now, note Ck = 1/T0 X(kω0).
So, going back to the very first expression, we can write the series for xP(t)
as:
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 14/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
Let's press on. Taking the limit of both sides of the previous expression as
T0 goes to infinity we obtain:
What does the RHS equal? Let's rewrite it using Δw instead of ω0 (it
doesn't matter what symbol we use; I'm just trying to make the expression
look like something familiar):
Hopefully you now recognize the RHS as the Riemann sum of 1/2π X(ω)
exp(iωt) -- this is why I introduced the definition. Taking the limit, we
therefore obtain:
where, as before:
Footnote: You'll see many variations of what I have written as the Fourier
transform. Some authors use a negative exponent in the definition of x(t)
and a positive exponent in X(ω). Some authors move the leading 1/2π to
X(ω), or put a 1/√2π on both for total symmetry bonus points (you can use
whatever leading constant you like as long as their product equals 1/2π).
Some people go back to using f instead of ω which makes the leading
constant equal to 1 instead of 1/2π. It's all very confusing.
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 16/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
prove, but a picture is worth a thousand proofs:
Here the traces stand in for three different X(ω) returned by the DTFT.
When we sample these, we lose information. Squint and look at the dots.
The three sampled waveforms (dots) are identical even though the original
waveforms are not. This is called aliasing. You can construct at most N/2
unique frequency components from any continuous function sampled at N
locations; if you try to generate more, you start repeating components you
already have. We saw an example of this back in Section II when we
applied our algorithm to data of length 2.
where
I'll have more to say about the DFT in Part II, for the DFT is the rock upon
which Matlab's fft( ) function is built (and that's just the beginning of the
bizarre goings on inside the DFT). So for now, a summary: Sampled data is
finite and therefore non-periodic. Ergo, a proper Fourier representation
requires infinitely many frequencies. But sampled data can only represent
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 17/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
a finite collection of frequencies. Something has to give. The compromise
is the DFT does an implicit periodic extension behind your back. This is
what I mean when I say the DFT works on "quasiperiodic" data (a term I
made-up -- don't expect to find it elsewhere). Some authors use DFS when
x[k] is literally periodic and DTFT when x[n] includes an explicit periodic
extension, reserving the term DFT for when x[n] is merely assumed to be
periodic. Those distinctions make for much confusion when encountering
Fourier for the first time. To simplify, I lump them all under a single moniker:
"Discrete Fourier Transform." Purists and Wikipedia crazies will disapprove.
Consider yourself warned.
How fast is it? Crazy fast.* For all intensive porpoises, the FFT is free,
computationally speaking. In any significant application that includes the
FFT, some other part of the processing will be your speed bottleneck.
Guaranteed. Cooley and Tukey should have won a Nobel prize for the FFT.
They should be household names.
We won't get into the FFT algorithm, either presently or in Part II. IIRC,
Matlab's fft( ) uses the Cooley and Tukey approach (called the Radix-2)
probably with some proprietary tweaks. For us it will remain a black box.
We are interested in what comes out of the FFT, what the coefficients tell
us and how they can be used. However, people often (incorrectly) use
"FFT" as a synonym for the DFT, or even as a synonym for "Fourier
analysis," so it's good you know how it fits into the big picture. The big
picture is: FFT = fast DFT.
The goal when I started writing A LabKitty Primer on Fourier Analysis was
to explain the vector of numbers returned by the Matlab/Octave fft( )
function. If you understand those, I claim, you understand Fourier analysis.
Our goal has not changed. And while we have come far, we are not there
yet. And, alas, we're not going to get there today. In describing fft( ), I
quickly realized there's a host of new concepts must deal with. Aliasing.
Nyquist frequency. Vector folding. Windowing. These concepts will need
proper decyphering before we get to the end of our journey, before we
finally chuck the ring into Mt. Doom. As Peter Jackson has taught us: Why
do anything in one part when making a trilogy triples the box?
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 18/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
I do not have a trilogy, but I do have a sequel. FFT II: Electric Boogaloo.
Nerds in Paradise. FFT Harder. Whatever. But feel free to pause here for a
rest if need be. Like Frodo in Riverdance. Sample the lamba bread. Visit
the wenchkeep. Enjoy a beverage in a quality LabKitty beverage container.
Can't stress that last part enough.
When you are ready to continue, click here: A LabKitty Primer on Fourier
Analysis Part II. More wonders await.
2 comments:
Kitten September 28, 2016 at 7:42 PM
Hi. Nice post! I'm getting multiples in amplitude in my reconstructed signal, as you noted happens. I'd
like to know what you will write about this in Part II, specifically how you said you'd explain further why it
is happening and what the proper solution is. I see you gave a couple hints, but they don't lend to me a
full explanation to the problem in my situation. I was looking at a couple different signals and in both of
them I'm getting a multiple of 5 when I look at 50 constants. In one, I have a sampling rate of 1kHz and
10 samples. In the other, I have a sampling rate of 200 Hz and 20 samples. I'd appreciate it if you can
explain further why this is happening and what the proper solution is. (I'll only look at the first # of
samples/2 constants for now!) Thanks!
Reply
Replies
The short answer is: If your sampling rate is Fs (say 200 Hz), you should not attempt to
reconstruct any components beyond Fs/2 (100 Hz, in your example). The cutoff is called the
Nyquist frequency and the multiple samples are due to something called aliasing (which is
introduced in the figure in which three different sinewaves all produce the same sampled
waveform -- multiple frequencies in the reconstructed signal is kinda this effect in reverse).
Alas, Part II of the Primer has been delayed indefinitely. I've been posting shorter articles but
these Primers take *forever* to write!
Reply
Enter Comment
The content provided herein is solely the work of the author in my personal capacity and does not reflect the attitudes, positions, or opinions of any institution,
university, or corporate entity I am currently or have been previously affiliated with in any capacity.
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 19/20
1/31/25, 1:29 PM LabKitty: A Primer on Fourier Analysis -- Part I
https://www.labkitty.com/2015/12/a-primer-on-fourier-analysis-part-i.html 20/20