Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FFT in numpy vs FFT in MATLAB do not have the same results

I have a vector with complex numbers (can be found here), both in Python and in MATLAB. I am calculating the ifft-transformation with

ifft(<vector>) 

in MATLAB and with

np.fft.ifft(<vector>)

in Python. My problem is that I get two completely different results out of it, i.e. while the vector in Python is complex, it is not in MATLAB. While some components in MATLAB are zero, none are in Python. Why is that? The fft-version works as intended. The minimal values are at around 1e-10, i.e. not too low.

like image 959
arc_lupus Avatar asked May 12 '16 14:05

arc_lupus


People also ask

Does numpy have fft?

Numpy fft. fft() is a function that computes the one-dimensional discrete Fourier Transform. The numpy fft. fft() method computes the one-dimensional discrete n-point discrete Fourier Transform (DFT) with the efficient Fast Fourier Transform (FFT) algorithm [CT].

What does numpy fft Fftfreq do?

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


1 Answers

Actually, they are the same but Python is showing the imaginary part with extremely high precision. The imaginary components are being shown with values with a magnitude of around 10^{-12}.

Here's what I wrote to reconstruct your problem in MATLAB:

format long g;
data = importdata('data.txt');
out = ifft(data);

format long g; is a formatting option that shows you more significant digits where we show 15 significant digits including decimal places.

When I show the first 10 elements of the inverse FFT output, this is what I get:

>> out(1:10)

ans =

         -6.08077329443768
         -5.90538963023573
         -5.72145198564976
         -5.53037208039314
         -5.33360059559345
         -5.13261402212083
         -4.92890104744583
         -4.72394865937531
         -4.51922820694745
         -4.31618153490126

For numpy, be advised that complex numbers are read in with the j letter, not i. Therefore when you load in your text, you must transform all i characters to j. Once you do that, you can load in the data as normal:

In [15]: import numpy as np

In [16]: with open('data.txt', 'r') as f:
   ....:     lines = map(lambda x: x.replace('i', 'j'), f)
   ....:     data = np.loadtxt(lines, dtype=np.complex)

When you open up the file, the call to map would thus take the contents of the file and transform each i character into j and return a list of strings where each element in this list is a complex number in your text file with the i replaced as j. We would then call numpy.loadtxt function to convert these strings into an array of complex numbers.

Now when I take the IFFT and display the first 10 elements of the inversed result as we saw with the MATLAB version, we get:

In [20]: out = np.fft.ifft(data)

In [21]: out[:10]
Out[21]: 
array([-6.08077329 +0.00000000e+00j, -5.90538963 +8.25472974e-12j,
       -5.72145199 +3.56159535e-12j, -5.53037208 -1.21875843e-11j,
       -5.33360060 +1.77529105e-11j, -5.13261402 -1.58326676e-11j,
       -4.92890105 -6.13731196e-12j, -4.72394866 +5.46673985e-12j,
       -4.51922821 -2.59774424e-11j, -4.31618154 -1.77484689e-11j])

As you can see the real part is the same but the imaginary part still exists. However, note how small in magnitude the imaginary components are. MATLAB in this case chose to not display the imaginary components because their magnitudes are very small. Actually, the data type returned from the ifft call in MATLAB is real so there was probably some post-processing after ifft was called to discard these imaginary components. numpy does not do the same thing by the way but you might as well consider these components to be very small and insignificant.


All in all, both ifft calls in Python and MATLAB are essentially the same but the imaginary components are different in the sense that Python/numpy returns those imaginary components even though they are insignificant where as the ifft call in MATLAB does not. Also take note that you need to ensure that the imaginary variable is replaced with j and you can't use i as in the original text file you've provided. If you know for certain that the output type should be real, you can also drop the imaginary components by giving a call to numpy.real on the ifft result if you so wish.

like image 161
rayryeng Avatar answered Sep 28 '22 05:09

rayryeng