4

First of i know there is an identical question with answer in SO here: FFT in Matlab and numpy / scipy give different results but the answer given there does not work on the test i did:

when i do an fft from numpy.fft i get following result:

In [30]: numpy.fft.fft(numpy.array([1+0.5j, 3+0j, 2+0j, 8+3j]))
Out[30]: array([ 14.+3.5j,  -4.+5.5j,  -8.-2.5j,   2.-4.5j])

which is identical to the output of in my case octave)

octave:39> fft([1+0.5j,3+0j,2+0j,8+3j])
ans =
Columns 1 through 3:
14.0000 +  3.5000i   -4.0000 +  5.5000i   -8.0000 -  2.5000i
Column 4:
2.0000 -  4.5000i

but if i transpose the list in octave and python i get:

In [9]: numpy.fft.fft(numpy.array([1+0.5j, 3+0j, 2+0j, 8+3j]).transpose())
Out[9]: array([ 14.+3.5j,  -4.+5.5j,  -8.-2.5j,   2.-4.5j])

and for octave:

octave:40> fft([1+0.5j,3+0j,2+0j,8+3j]')
ans =

14.0000 -  3.5000i
2.0000 +  4.5000i
-8.0000 +  2.5000i
-4.0000 -  5.5000i

I also tried to reshape in python but this results in:

In [33]: numpy.fft.fft(numpy.reshape(numpy.array([1+0.5j,3+0j,2+0j,8+3j]), (4,1)))
Out[33]: 
array([[ 1.+0.5j],
   [ 3.+0.j ],
   [ 2.+0.j ],
   [ 8.+3.j ]])

how do i get the same result in python as in octave? + i don't have matlab to test, otherwise i would check if it returns the same as octave just to be sure.

Community
  • 1
  • 1
Xtroce
  • 1,749
  • 3
  • 19
  • 43
  • Matlab 2014a gives me: `14.0000 + 3.5000i -4.0000 + 5.5000i -8.0000 - 2.5000i 2.0000 - 4.5000i` Please always add the version numbers of your tools. If possible, switch to the newest available version. – usr1234567 Nov 27 '14 at 13:21
  • the numpy version is 1.8.2 octave is 3.8.1 on x64 – Xtroce Nov 27 '14 at 14:23

1 Answers1

5

Why NumPy and octave gave different results:

The inputs were different. The ' in octave is returning the complex conjugate transpose, not the transpose, .':

octave:6> [1+0.5j,3+0j,2+0j,8+3j]'
ans =

   1.0000 - 0.5000i
   3.0000 - 0.0000i
   2.0000 - 0.0000i
   8.0000 - 3.0000i

So to make NumPy's result match octave's:

In [115]: np.fft.fft(np.array([1+0.5j, 3+0j, 2+0j, 8+3j]).conj()).reshape(-1, 1)
Out[115]: 
array([[ 14.-3.5j],
       [  2.+4.5j],
       [ -8.+2.5j],
       [ -4.-5.5j]])

octave:7> fft([1+0.5j,3+0j,2+0j,8+3j]')
ans =

   14.0000 -  3.5000i
    2.0000 +  4.5000i
   -8.0000 +  2.5000i
   -4.0000 -  5.5000i

In NumPy, the transpose of a 1D array is the same 1D array. That's why fft(np.array([1+0.5j, 3+0j, 2+0j, 8+3j]).transpose()) returns a 1D array.

Reshaping after taking the FFT of a 1D array:

You could take the FFT first, and then reshape. To make a 1D array 2-dimensional you could use reshape to obtain a column-like array of shape (4,1), or use np.atleast_2d followed by transpose:

In [115]: np.fft.fft(np.array([1+0.5j, 3+0j, 2+0j, 8+3j]).conj()).reshape(-1, 1)
Out[115]: 
array([[ 14.-3.5j],
       [  2.+4.5j],
       [ -8.+2.5j],
       [ -4.-5.5j]])

or

In [116]: np.atleast_2d(np.fft.fft(np.array([1+0.5j, 3+0j, 2+0j, 8+3j]).conj())).T
Out[116]: 
array([[ 14.-3.5j],
       [  2.+4.5j],
       [ -8.+2.5j],
       [ -4.-5.5j]])

Taking the FFT of a 2D array:

np.fft.fft takes the FFT over the last axis by default. This is why reshaping to shape (4, 1) did not work. Instead, reshape the array to (1, 4):

In [117]: np.fft.fft(np.reshape(np.array([1+0.5j,3+0j,2+0j,8+3j]), (1,4)).conj()).T
Out[117]: 
array([[ 14.-3.5j],
       [  2.+4.5j],
       [ -8.+2.5j],
       [ -4.-5.5j]])

Or you could use np.matrix to make a 2D matrix of shape (1, 4). Again the FFT is taken over the last axis, returns an array of shape (1, 4), which you can then transpose to get the desired result:

In [121]: np.fft.fft(np.matrix([1+0.5j, 3+0j, 2+0j, 8+3j]).conj()).T
Out[121]: 
array([[ 14.-3.5j],
       [  2.+4.5j],
       [ -8.+2.5j],
       [ -4.-5.5j]])

This, perhaps, gives you the neatest syntax. But be aware that this passes a np.matrix as input but returns a np.ndarray as output.


As Warren Weckesser pointed out, if you already have a 2D NumPy array, and wish to take the FFT of its columns, then you could pass axis=0 to the call to np.fft.fft. Also, The matrix class (unlike the ndarray class) has a H property which returns the complex conjugate transpose. Thus

In [114]: np.fft.fft(np.matrix([1+0.5j, 3+0j, 2+0j, 8+3j]).H, axis=0)
Out[114]: 
array([[ 14.-3.5j],
       [  2.+4.5j],
       [ -8.+2.5j],
       [ -4.-5.5j]])
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • thanks for the answer, but i still have the same two problems, 1. the values are sorted differently, and second the signs of the imaginary parts aren't correct. the first one of the two is my problem since i try to build up a kernel from different fft's and i can't figure out why the sorting is different. Sorry for not being clear on that in the first place – Xtroce Nov 27 '14 at 14:20
  • If you first reshape the input to (4, 1), use `axis=0` in the call to `fft`. – Warren Weckesser Nov 27 '14 at 14:20
  • @unutbu Can I interest you in a bounty to solve a problem that seems to be related to the way the inverse FFT for a 2D array is computed? [The question is here.](https://stackoverflow.com/q/61718126/176769). – karlphillip May 17 '20 at 21:22