Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

extracting phase information using numpy fft

Tags:

python

numpy

fft

I am trying to use a fast fourier transform to extract the phase shift of a single sinusoidal function. I know that on paper, If we denote the transform of our function as T, then we have the following relations:

enter image description here

However, I am finding that while I am able to accurately capture the frequency of my cosine wave, the phase is inaccurate unless I sample at an extremely high rate. For example:

import numpy as np
import pylab as pl

num_t = 100000
t = np.linspace(0,1,num_t)
dt = 1.0/num_t
w = 2.0*np.pi*30.0
phase = np.pi/2.0

amp = np.fft.rfft(np.cos(w*t+phase))
freqs = np.fft.rfftfreq(t.shape[-1],dt)

print (np.arctan2(amp.imag,amp.real))[30]

pl.subplot(211)
pl.plot(freqs[:60],np.sqrt(amp.real**2+amp.imag**2)[:60])
pl.subplot(212)
pl.plot(freqs[:60],(np.arctan2(amp.imag,amp.real))[:60])
pl.show()

Using num=100000 points I get a phase of 1.57173880459.

Using num=10000 points I get a phase of 1.58022110476.

Using num=1000 points I get a phase of 1.6650441064.

What's going wrong? Even with 1000 points I have 33 points per cycle, which should be enough to resolve it. Is there maybe a way to increase the number of computed frequency points? Is there any way to do this with a "low" number of points?

EDIT: from further experimentation it seems that I need ~1000 points per cycle in order to accurately extract a phase. Why?!

EDIT 2: further experiments indicate that accuracy is related to number of points per cycle, rather than absolute numbers. Increasing the number of sampled points per cycle makes phase more accurate, but if both signal frequency and number of sampled points are increased by the same factor, the accuracy stays the same.

like image 549
KBriggs Avatar asked Mar 15 '16 18:03

KBriggs


People also ask

What FFT does Numpy use?

numpy. fft promotes float32 and complex64 arrays to float64 and complex128 arrays respectively. For an FFT implementation that does not promote input arrays, see scipy. fftpack .

What does Numpy FFT Fftfreq do?

fft. fftfreq. Return the Discrete Fourier Transform sample frequencies.

What is the significance of NP FFT FFT?

This function computes the one-dimensional n-point discrete Fourier Transform (DFT) with the efficient Fast Fourier Transform (FFT) algorithm [CT]. Input array, can be complex. Length of the transformed axis of the output. If n is smaller than the length of the input, the input is cropped.

How many phases are there in FFT?

Functional Family Therapy is conducted in a home-based or clinical-based environment and delivered across five separate phases, with intervention typically spanning 3-5 months.


2 Answers

Your points are not distributed equally over the interval, you have the point at the end doubled: 0 is the same point as 1. This gets less important the more points you take, obviusly, but still gives some error. You can avoid it totally, the linspace has a flag for this. Also it has a flag to return you the dt directly along with the array.

Do

t, dt = np.linspace(0, 1, num_t, endpoint=False, retstep=True)

instead of

t = np.linspace(0,1,num_t)
dt = 1.0/num_t

then it works :)

like image 144
Ilja Avatar answered Oct 04 '22 03:10

Ilja


The phase value in the result bin of an unrotated FFT is only correct if the input signal is exactly integer periodic within the FFT length. Your test signal is not, thus the FFT measures something partially related to the phase difference of the signal discontinuity between end-points of the test sinusoid. A higher sample rate will create a slightly different last end-point from the sinusoid, and thus a possibly smaller discontinuity.

If you want to decrease this FFT phase measurement error, create your test signal so the your test phase is referenced to the exact center (sample N/2) of the test vector (not the 1st sample), and then do an fftshift operation (rotate by N/2) so that there will be no signal discontinuity between the 1st and last point in your resulting FFT input vector of length N.

like image 43
hotpaw2 Avatar answered Oct 04 '22 04:10

hotpaw2