Skip to content

Instantly share code, notes, and snippets.

@friedbrice
Created January 13, 2017 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save friedbrice/ea27eec02bc58b2417329e5e4a162078 to your computer and use it in GitHub Desktop.
Save friedbrice/ea27eec02bc58b2417329e5e4a162078 to your computer and use it in GitHub Desktop.
Work These Days
def fourier_series(n, samples):
"""
`fourier_series`
From a list of `samples` taken from an unknown periodic function,
returns the best-fit `n`-term sine/cosine approximation of the
unknown function.
Args:
param1 (int): The number of terms you want in your
approximation.
param2 (list): The list of samples from your unknown periodic
function.
Returns:
(list): The return value. List of 3-tuples of numbers, where the
first entry is the frequency, the second entry is the
coefficient of cosine, and the third entry is the coefficient of
sine.
Contract:
- `samples` must be drawn from a (presumably unknown) periodic
function of time.
- The `samples` must be given in increasing chronological order.
- The time interval between samples must be constant.
- The number of samples must be an integer multiple of a full
period. No Fractions of Periods Allowed.
`fourier_series`s return is only meaningful if the contract is met.
If you fail to meet the contract, the algorithm won't complain, but
it will return what appears to be a coherent result that is actually
Total Shit, leading to grossly-inaccurate forcasts.
"""
import cmath
import heapq
from numpy import fft
s = len(samples)
freq_domain = zip(range(1, s + 1), fft.fft(samples))
modulus = lambda p: cmath.polar(p[1])[0]
scale = lambda p: (p[0], p[1].real / s, p[1].imag / s)
series = map(scale, heapq.nlargest(n, freq_domain, modulus))
return list(series)
def eval_series(series, t):
"""
`eval_series`
Find the value of the given Fourier `series` at the argument `t`.
Args:
param1 (list): A list of 3-tuples that represents the Fourier
series where the first entries are the
frequencies, the second entries are the
coefficients of cosine, and the third entries are
the coefficients of sine.
param2 (double): The argument `t` to the Fourier `series`.
Return:
(double): The value of the Fourier `series` at the argument `t`.
"""
import math
cosf = lambda frq, amp, t: amp * math.cos(frq * 2 * math.pi * t)
sinf = lambda frq, amp, t: amp * math.sin(frq * 2 * math.pi * t)
opr = lambda tup: cosf(tup[0], tup[1], t) + sinf(tup[0], tup[2], t)
return sum(map(opr, series))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment