A fancier brute-force DFT implementation using NumPy features
def dft2(f):
f = np.asarray(f)
N = f.shape[0]
W = np.exp(-2 * np.pi * 1.0j / N)
k = np.arange(N)
jk = np.outer(k, k)
M = W**jk
return np.dot(M, f)
f = data_piano[:2000]
F = dft2(f)
N = len(f)
dx = 1. / sampling_rate
freq = 1.0 / (N * dx) * np.arange(N)
plt.plot(freq[:100], F.real[:100])
F_numpy = np.fft.fft(f)
frequency_numpy = np.fft.fftfreq(N, dx)
print(np.allclose(F, F_numpy))
plt.plot(frequency_numpy[:100], F_numpy[:100].real)
Our algorithm dft2 also produces the same result as fft from NumPy.
Timing with size
import random
Ntest = 10
timings2 = []
dimension2 = []
for i in range(1, Ntest):
f = [random.gauss(0, 1) for n in range(2**i)]
timing = %timeit -o -n 1 dft2(f)
dimension2.append(2**i)
timings2.append(timing.average)
plt.subplot(121)
plt.plot(np.array(dimension2), np.array(timings2), 'o', markersize=12, color='red')
plt.plot(np.array(dimension2), np.array(timings2), color='red')
plt.xlabel("$N$")
plt.ylabel("Timing / s")
plt.subplot(122)
plt.plot(np.array(dimension2)**2, np.array(timings2), 'o', markersize=12, color='red')
plt.plot(np.array(dimension2)**2, np.array(timings2), color='red')
plt.xlabel("$N^2$")
plt.show()