4
$\begingroup$

I have a function that I sample from over one period. I want to use the Fourier Transform to learn the function and then predict unsampled values. Please see the code below:

import numpy as np
import matplotlib.pyplot as plt

# Sample from the function for one period
t = np.linspace(0,1, num=30) * 2*np.pi
samples = np.cos(t) + np.sin(2*t + 2*np.pi/3)
plt.scatter(t, samples)

# Fourier transform
dft_coef = np.fft.fft(samples)

# Predict outcome for arbitrary not observed angle t'
def predict(t_, dft_coef):
    # TODO

Here is the plot:

enter image description here

The goal is to write a function predict that will calculate arbitrary values of the function. Can someone help me go from this discrete case to continuous prediction?

$\endgroup$

3 Answers 3

3
$\begingroup$

If your signal is periodic you can simply interpolate by padding zeros in the frequency domain. This is equivalent to infinite circular sinc() interpolation and will in your case give "ideal" results.

In general the process is called "up sampling": the generic to do this is to insert zeros between the existing samples and than filter with a suitable low-pass or "interpolation" filter to remove the mirror images of the spectrum. Typically that's done using a polyphase FIR filter.

$\endgroup$
1
  • $\begingroup$ any code that I can use? $\endgroup$
    – falematte
    Nov 8, 2023 at 18:09
2
$\begingroup$

I found this post from googling "numpy fft interpolation", and since the accepted answer does not do what the question asked I thought I would supply my solution for FFT interpolating arbitrary values:

def fft_interp(coeffs, x):
    # 1D FFT interpolate for arbitrary x
    # assume x is periodic on [0,1] interval
    size = len(coeffs)
    kn = np.fft.fftfreq(size)
    eikx = np.exp(2.j*np.pi*x*size*kn)
    return np.dot(coeffs, eikx) / size

and here is for an array of arbitrary values:

def fft_interp_vec(coeffs, xv):
    size = len(coeffs)
    kn = fft.fftfreq(size)
    eikx = np.exp( 2.j*np.pi*size*np.outer(xv, kn) )
    return np.einsum('ab,b->a', eikx, coeffs) / size
$\endgroup$
0
$\begingroup$

You can just join the lines by linear interpolation, Or use preexisting libraries like scipy. The method you are looking for is scipy.interpolate.interp2d.

$\endgroup$
1
  • $\begingroup$ Linear interpolation gives poor results for higher frequencies. If you want to use standard interpolation, a spline or Lagrange would work better. $\endgroup$
    – Hilmar
    Aug 23, 2021 at 10:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.