Skip to content
scipython.com

P6.7.2Fourier expansion of a square wave

A square wave of period \(T\) may be defined through the following function:

\[f_\mathrm{sq}(t) = \left\{ \begin{array}{ll} 1 & t < T/2 \\ -1 & t \ge T/2 \end{array} \right.\]

with \(f(t) = f(t + nT)\) for \(n=\pm 1, \pm 2, \cdots\).

Plot the square wave with \(T=1\) (and hence cycle frequency, \(\nu=1\)) for \(0 \le t < 2\) taking a grid of 2048 time points over this interval. Calculate and plot its discrete Fourier Transform.

The Fourier expansion of this function is the infinite series

\[f_\mathrm{sq}(t) = \frac{4}{\pi} \sum_{k=1}^{\infty} \frac{1}{2k-1}\sin[2\pi(2k-1)\nu t]\]

Compare the square wave function with this Fourier expansion truncated at 3, 9 and 18 terms. Also compare their (suitably normalized) Fourier transforms: the missing frequencies in each truncated series should appear as zeros in its Fourier transform, whereas the present terms will have intensities \(4/[\pi(2k-1)]\).

Show solution

The three cases are handled in the code below.

fouriersquarewave
import numpy as np
import matplotlib.pyplot as plt

n = 2048
T = 1
freq = 1 / T
duration = 2
t = np.arange(0, duration, duration / n)
f = np.ones(n)
f[(t >= T / 2) & (t < T)] = -1
f[t >= T] = f[t < T]

# 3x2 subplots, with total figure size of 6.4" x 7.2".
fig, axes = plt.subplots(nrows=3, ncols=2, figsize=(6.4, 7.2))


def fourier_expansion(nterms):
    fourier_square = np.zeros(n)
    for k in range(1, nterms + 1):
        fac = 2 * k - 1
        fourier_square += np.sin(2 * np.pi * fac * freq * t) / fac
    return 4 / np.pi * fourier_square


for i, nterms in enumerate((3, 9, 18)):
    fourier_square = fourier_expansion(nterms)

    F = (duration / n) / (4 / np.pi) * np.abs(np.fft.rfft(fourier_square))
    Fdft = (duration / n) / (4 / np.pi) * np.abs(np.fft.rfft(f))
    Ffreq = np.fft.rfftfreq(n, duration / n)

    ax = axes[i, 0]
    ax.plot(t, f)
    ax.plot(t, fourier_square)
    ax.set_xlabel(r"$t\;/\mathrm{s}$")
    ax.set_ylabel(r"$f_\mathrm{sq}(t)$")
    ax.set_ylim(-1.5, 1.5)

    ax = axes[i, 1]
    ax.bar(Ffreq, F, color="g")
    ax.set_xlabel("Fourier expansion term number")
    ax.set_ylabel("Fourier term coefficient")
    ax.set_xlim(0, 50)
    ax.set_ylim(0, 1.1)

plt.tight_layout()
plt.show()

The plot produced by this code is shown below.

The Fourier expansion of a square wave with 3, 6 and 9 terms
The Fourier expansion of a square wave with 3, 6 and 9 terms.