Last active
May 30, 2020 04:37
-
-
Save rsokl/9fc66190035ed8ff452f1fc6820baa2c to your computer and use it in GitHub Desktop.
Returns individual terms of inverse DFT of a function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def get_fourier_components( | |
func, num_samples, domain_length, sort_by_descending_magnitude=False | |
): | |
""" | |
Returns the N // 2 + 1 amplitude-phase terms of the inverse D series | |
of func(t), where funct t is evaluated on [0, T) in N evenly-spaced points. | |
I.e each component | |
A[k] cos(2*pi * f[k] * t + phi[k]) | |
is returned in a 2D array for each frequency component and each time. | |
Parameters | |
---------- | |
func : Callable[[numpy.ndarray], numpy.ndarray] | |
A vectorized function whose fourier components are being evaluated | |
num_samples : int | |
The number of samples used, N | |
domain_length : float | |
The upper bound, T, on the sampling domain: [0, T) | |
sort_by_descending_magnitude : bool, default=False | |
If True, the components are returned in order of decreasing amplitude | |
Returns | |
------- | |
numpy.ndarray, shape-(N // 2 + 1, N) | |
Axis-0 carries the respective fourier components. I.e. element-k returns | |
the shape-(N,) array vectorized over times: | |
A[k] cos(2*pi * f[k] * t + phi[k]) (where t is shape-(N,)) | |
Thus calling `out.sum(axis=0)` on the output returns `func(t)` | |
""" | |
N = num_samples | |
L = domain_length | |
# evaluate on [0, N) | |
t = np.arange(N) * (L / N) | |
ck = np.fft.rfft(func(t)) # shape-(N,) | |
amps = np.abs(ck) | |
phases = np.arctan2(ck.imag, ck.real) | |
times = t[:, None] | |
freqs = np.arange(N // 2 + 1) / L | |
# shape-(N, N) - time vs freq | |
out = amps * np.cos((2 * np.pi * freqs) * times + phases) / N | |
const = out[:, 0] | |
out = out[:, 1:] * 2 # need to double count for n, N-n folding | |
out = np.hstack([const[:, None], out]).T # transpose: freq vs time | |
if sort_by_descending_magnitude: | |
out = out[np.argsort(amps), :][::-1] | |
return out |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
plotting: