This notebook is part of a guest lecture I gave in our introductory signal processing class, ELEG 305, on St. Patrick's Day.
The command below loads numpy (the vector processing library) and matplotlib (Matlab-style plotting) and tells the notebook to draw the plots in place. Many Ipython notebooks start with this command.
%pylab inline
Let's plot a sine wave. The Nyquist theorem says we have to sample at least twice per period. Let's try it.
f = 1
Fs = 2.1 #more than twice per period
t = linspace(0,3,3*Fs+1)
y = sin(2*pi*f*t)
plot(t,y)
That didn't work. Clearly the plotting routine does not understand the Nyquist criterion (neither, by the way, does Matlab's plotting routine).
We need to increase the sampling rate.
f = 1
Fs = 100 #a lot more than twice per period
t = linspace(0,3,3*Fs+1)
y = sin(2*pi*f*t)
plot(t,y)
That's better. They look like sinusoids.
Various plots of sines and cosines on both axes.
t = linspace(0,1,201)
wt = 2*pi*t
plot(cos(wt), sin(wt))
axes().set_aspect('equal')
In the plots below, play with the frequencies and the phase shift to change the picture. There are many interesting Lissajous figures.
plot(cos(4*wt),cos(3*wt+pi/5))
axes().set_aspect('equal')
Let's improve the picture a bit by increasing the box size a little.
X=cos(2*wt)
Y=cos(3*wt+pi/4)
axes().set_aspect('equal')
xlim(X.min() * 1.1, X.max() * 1.1)
ylim(Y.min() * 1.1, Y.max() * 1.1)
plot(X,Y)
With a small change, we can generate other shapes. Here we want successive time values to be relatively far apart so the points on the circle jump around.
Let's also eliminate the box.
tt=0.4*arange(0,6)
plot(cos(2*pi*tt),cos(2*pi*tt+pi/2))
axes().set_aspect('equal')
axes().axis('off') #comment out to get box back
The Fourier series for a square wave is the following:
\[sq(t) = \frac{4}{\pi}\sum_{\text{$k=1$, $k$ odd}}^\infty \frac{\sin(2\pi k f t)}{k} = \frac{4}{\pi} \left( \sin(2\pi f t) + (1/3) \sin(2\pi 3 f t) + (1/5)\sin(2\pi 5 ft) + \ldots\right)\]
The various frequencies are called harmonics. The first harmonic is also called the fundamental. Notice this series has only odd terms. I.e., all the even harmonics are 0. (Other Fourier series may have non-zero even terms.)
Let's look at a some approximations to the square wave.
t = linspace(0,2,201) #two cycles, 100 points each
y1 = (4/pi)*sin(2*pi*f*t)
y3 = y1 + (4/(3*pi))*sin(2*pi*3*f*t)
y5 = y3 + (4/(5*pi))*sin(2*pi*5*f*t)
sqwave = sign(sin(2*pi*f*t)) #an actual square wave
plot(t,y1, t,y3, t,y5, t, sqwave)
We can clearly see we are approaching a square wave. Let's add a bunch more terms, but let's also do it more efficiently.
sq = zeros(len(t)) #preallocate the output array
for h in arange(1,25,2):
sq += (4/(pi*h))*sin(2*pi*f*h*t)
plot(t,sq, t,sqwave)
Those little peaks near the discontinuities are called Gibbs Phenomena. As long as we have a finite number of terms, no matter how many, we will have Gibbs phenomena.
Note, if we change the sine to cosine the final picture looks a lot different. Phase matters.
not_sq = zeros(len(t))
for h in arange(1,15,2):
not_sq += (4/(pi*h))*cos(2*pi*f*h*t)
plot(t,not_sq, t,sqwave)
C. Boncelet, 17 March 2014, rev. 30 April 2014