In short, I can reproduce the original x[n] from DFT via IDFT. However this happens only when I take samples DFT from 0 to 2pi. When DFT is ranging from -1pi to 1pi, the reproduced x[n] is not correct.
I wonder if I do something wrong with the code or it's the fact. Following are 5 steps of my codes in Python.
- Generate a signal
n = np.arange(0, 100)
a1 = 3
a2 = 1
a3 = 0.2
f1 = 1/25
f2 = 1/9
f3 = 1/4
phi1 = 1/2*pi # 90 degress
phi2 = 1/6*pi # 30 degrees
phi3 = 1*pi # 180 degrees
sig1 = a1*np.sin(2*pi*f1*n + phi1)
sig2 = a2*np.sin(2*pi*f2*n + phi2)
sig3 = a3*np.sin(2*pi*f3*n + phi3)
x = (sig1 + sig2 + sig3)
- Function to calculate DFT from time domain signal
$X(\omega_k)=X(k)=\sum_{n=0}^{N-1}x_n \cdot e^{-j\frac{2\pi}{N}kn}$
def dft(omega: float, x: np.ndarray) -> complex:
"""Calculate complex number of input omega, given a time domain x
Args:
omega (float): in pi
x (np.ndarray): signal in time domain
Returns:
complex: information of omega in x
"""
n = np.arange(0, len(x))
sinusoid = np.e**(-1j*omega*pi*n)
result = np.dot(x, sinusoid)
return result
- Omega ranging from -1pi to 1pi, length equals length of x[n]
K = round(len(x) * (1)) # length of DFT
omegas = np.linspace(-1, 1, K + 1) # ranging from -1pi to 1pi
omegas = omegas[:-1] # remove the last redundant element
X = [dft(omega, x) for omega in omegas]
- Function to calculate IDFT
$x(n)=\frac{1}{K}\sum_{k=0}^{K-1}X_k \cdot e^{j\frac{2\pi}{K}kn}$
def idft(n: int, X: list) -> float:
"""Inverse DFT: calcuate time domain from frequency domain
Args:
n (int): index of time
X (list): frequency domain
Returns:
float: magnitude of the signal at time n
"""
k = np.arange(0, len(X))
sinusoid = np.e**(1j*2*pi/len(X)*k*n)
result = np.dot(X, sinusoid) / len(X)
return result
- Reproduce x[n]
time_idx = np.arange(0, 100, 1)
x_repro = [idft(n, X) for n in time_idx]
x_repro = [x.real for x in x_repro]
x_repro = pd.Series(x_repro, index=time_idx)
I will provide a derivation how the DFT between $-\pi$ and $\pi$ can be inverted. The mistake in your code is that you have not correctly adapted the IDFT.
Assume for simplicity that $N$ is even. The derivation works almost the same if $N$ is odd. Define the shifted DFT as $$ X'(k)=\sum_{n=-N/2}^{N/2-1}x(n)e^{-j 2\pi k \frac{n}{N}}, $$ where the frequencies range from $-\pi$ to $\pi$ as desired. Then, $$ X'(k)=\sum_{n=0}^{N-1}x(n)e^{-j 2\pi k \frac{n-N/2}{N}}=\sum_{n=0}^{N-1}x(n)e^{-j 2\pi k \frac{n}{N}}e^{j\pi k}=(-1)^k\sum_{n=0}^{N-1}x(n)e^{-j 2\pi k \frac{n}{N}}, $$ where we used that $e^{j\pi}=-1$ in the last equality. So, if we let $X(k)$ denote that standard DFT of $x(n)$, we see that $ X(k)=(-1)^kX'(k) $. Hence, the shifted DFT is inverted by $$ x(n) = \frac{1}{N}\sum_{k=0}^{N-1}X(k)e^{j 2\pi k \frac{n}{N}}= \sum_{k=0}^{N-1}(-1)^kX'(k)e^{j 2\pi k \frac{n}{N}}. $$ In other words, you obtain the inverse by multiplying the spectrum with $(-1)^k$ and then computing the standard IDFT.