5.4.7Scientific Computing (Python)

NumPy FFT — np.fft module

1,940 words9 min readdifficulty · medium

WHY does this exist?


WHAT is the DFT? (derive it from scratch)

Where does e2πikn/Ne^{-2\pi i kn/N} come from?

WHY this exact formula? Think of testing your signal against a probe wave.

  • A pure wave of frequency kk (over NN samples) is wn=e+2πikn/Nw_n = e^{+2\pi i kn/N} — it spins around the unit circle kk full turns as nn goes 0N0\to N.
  • To ask "how much of wave kk is in xx?", take the inner product (correlation): multiply each sample by the conjugate of the probe and sum.
  • Conjugate of e+2πikn/Ne^{+2\pi i kn/N} is e2πikn/Ne^{-2\pi i kn/N}. Hence the minus sign.

We can prove orthogonality (geometric series of roots of unity): n=0N1e2πi(km)n/N={Nk=m0km\sum_{n=0}^{N-1} e^{2\pi i (k-m) n/N} = \begin{cases} N & k=m \\ 0 & k\neq m\end{cases} WHY: if k=mk=m each term is 11, sum =N=N. If kmk\ne m, it's a geometric series with ratio r=e2πi(km)/N1r=e^{2\pi i(k-m)/N}\ne1 and rN=1r^N=1, so 1rN1r=0\frac{1-r^N}{1-r}=0.

Inverse DFT

Because of orthogonality, we can recover xnx_n: xn=1Nk=0N1Xke+2πikn/Nx_n = \frac{1}{N}\sum_{k=0}^{N-1} X_k \, e^{+2\pi i kn/N} The 1N\tfrac1N and the ++ sign are exactly what undo the forward transform (NumPy's default convention).


HOW NumPy organizes the output

Figure — NumPy FFT — np.fft module

Worked Example 1 — find a tone

import numpy as np
fs   = 1000.0            # sampling rate, Hz
N    = 1000              # number of samples
t    = np.arange(N) / fs # time axis, seconds
x    = 3*np.sin(2*np.pi*50*t)   # a 50 Hz sine, amplitude 3
 
X    = np.fft.rfft(x)              # complex spectrum
f    = np.fft.rfftfreq(N, d=1/fs) # frequency axis
amp  = np.abs(X) * 2 / N          # convert to physical amplitude
 
print(f[np.argmax(amp)], amp.max())   # ~50.0 Hz, ~3.0
Step Why this step?
t = arange(N)/fs builds correct time stamps; total window T=N/fs=1T=N/f_s=1 s
rfft(x) real signal → half spectrum is enough
rfftfreq(N,d=1/fs) tells you which frequency each bin is — never hard-code!
*2/N DFT splits a real sine's energy into +f and −f; multiply by 2 and divide by NN to get the true amplitude 3

Worked Example 2 — reconstruct & verify inverse

x  = np.array([1.0, 2.0, 0.0, -1.0])
X  = np.fft.fft(x)
xr = np.fft.ifft(X)
print(np.allclose(x, xr.real))   # True

Why: ifft(fft(x)) == x exactly (up to float error) because the 1/N1/N and sign conventions are matched. Always trust round-trips to debug.


Worked Example 3 — DC and Nyquist

x = np.array([2,2,2,2], dtype=float)
print(np.fft.fft(x))   # [8.+0.j 0 0 0]

Why: a constant signal has only zero frequency (DC). Bin 0 equals xn=8\sum x_n = 8. All other bins are zero — there's no oscillation. The DC bin is always the sum of the samples.



Recall Feynman: explain to a 12-year-old

Imagine a music chord — many notes played at once, smashed into a single jiggle of the air. Your job: figure out which separate notes are inside. The FFT is a magic sieve: you hum each possible note at the jiggle, and whenever your hum matches a hidden note, it "rings" loudly; when it doesn't match, it stays silent. Do this for every note really cleverly (not one-by-one but all at once), and out pops a list: "this much of low note, this much of high note." That list is the spectrum. The "Fast" part is just a smart shortcut so it finishes before lunch.


Flashcards

What does np.fft.fft transform between?
Time (or spatial) domain ↔ frequency domain (complex output).
DFT formula for XkX_k?
Xk=n=0N1xne2πikn/NX_k=\sum_{n=0}^{N-1}x_n e^{-2\pi i kn/N}.
Why is the FFT "fast" — what complexity vs naive DFT?
O(NlogN)O(N\log N) vs O(N2)O(N^2).
Frequency of bin kk in Hz given rate fsf_s, length NN?
fk=kfs/Nf_k = k f_s / N.
What does np.fft.fftfreq(N, d) return?
The frequency of each bin (incl. negative freqs), spacing d=Δtd=\Delta t.
Difference between fft and rfft?
rfft assumes real input and returns only the N/2+1N/2+1 non-redundant bins.
What is the value of DFT bin 0 (DC)?
The sum of all samples nxn\sum_n x_n.
For a real sine of amplitude AA, how do you recover AA from |rfft|?
Multiply by 2/N2/N (use 1/N1/N for the DC bin).
Why is there a minus sign in the forward DFT exponent?
It's the conjugate of the probe wave used to correlate/measure each frequency.
What's the frequency resolution of an FFT?
Δf=fs/N=1/T\Delta f = f_s/N = 1/T, where TT is the total record length.
What does fftshift do and why?
Moves the zero-frequency component to the array center so negative/positive freqs plot symmetrically.
Property linking XkX_k and XNkX_{N-k} for real input?
XNk=XkX_{N-k}=\overline{X_k} (conjugate symmetry).

Connections

Concept Map

transformed by

fast version of

maps to

defined via

conjugate for

works because of

enables

recovers

naive cost

speeds up to

bin k gives

implemented in

Time domain signal

FFT algorithm

Discrete Fourier Transform

Frequency domain

Probe wave e^-2pi i kn/N

Correlation inner product

Orthogonality of waves

Inverse DFT

O of N^2

O of N log N

f_k equals k fs over N

np.fft functions

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho, FFT ka basic idea simple hai: koi bhi signal jo time ke saath badalta hai (jaise sound ya sensor reading), use hum alag-alag frequency ki sine/cosine waves ke sum ke roop mein likh sakte hain. FFT ek fast algorithm hai jo batata hai ki har frequency kitni "strong" hai signal ke andar. Microphone time ka data deta hai, lekin matlab to frequency mein hota hai — jaise music ka note ya pitch. Isiliye time domain se frequency domain ka bridge chahiye, aur wahi FFT karta hai.

Formula yaad rakho: Xk=xne2πikn/NX_k=\sum x_n e^{-2\pi i kn/N}. Yeh actually ek correlation hai — hum apne signal ko ek probe wave (frequency kk) ke saath multiply karke sum karte hain. Agar wahi frequency signal mein present hai, to sum bada aata hai; warna doosri frequencies aapas mein cancel ho jaati hain (orthogonality). Minus sign isliye hai kyunki probe wave ka conjugate use hota hai. "Fast" ka matlab — naive DFT O(N2)O(N^2) hota, FFT O(NlogN)O(N\log N), jo crores of samples ke liye game-changer hai.

NumPy mein practical cheezein: np.fft.fft ya real signal ke liye np.fft.rfft (yeh half spectrum deta hai, kyunki real signal symmetric hota hai). Aur sabse important — bin index ko Hz mat samajh lena! Hamesha np.fft.fftfreq(N, d=1/fs) ya rfftfreq use karke actual frequency nikalo, kyunki fk=kfs/Nf_k = k f_s/N. Amplitude recover karne ke liye real sine ko 2/N2/N se multiply karo (DC bin ke liye 1/N1/N).

Galtiyan jo sab karte hain: peak ki height ko directly amplitude samajh lena, ya frequency resolution bhool jaana (resolution =1/T=1/T, yaani jitna lamba recording, utni acchi pitch detection). Round-trip test (ifft(fft(x))==x) hamesha debugging ke liye use karo — confidence aata hai ki convention sahi hai. Bas itna samajh lo to FFT tumhare liye easy ho jayega!

Go deeper — visual, from zero

Test yourself — Scientific Computing (Python)

Connections