4
votes

I cannot make sense of this behavior of scipy. From the scipy.fftpack docs i learn that the output of fft is obviously complex and shaped like:

[y(0),y(1),..,y(n/2),y(1-n/2),...,y(-1)]         if n is even
[y(0),y(1),..,y((n-1)/2),y(-(n-1)/2),...,y(-1)]  if n is odd

so that if you plot something like np.abs(fft(signal)) you get the magnitude of the FFT.

If my signal is real-valued, then the negative frequencies give no information, and therefore one can use rfft to speed things up a little. And here comes what I don't understand: why is the output of rfft real valued, and shaped oddly like:

[y(0),Re(y(1)),Im(y(1)),...,Re(y(n/2))]              if n is even
[y(0),Re(y(1)),Im(y(1)),...,Re(y(n/2)),Im(y(n/2))]   if n is odd

Indeed with this definition, np.abs(rfft(signal)) gives you rubbish (you get alternately the absolute value of the real and imaginary parts of the FFT...), and you need some hacking to get the FFT magnitude. Why doesn't rfft it simply output complex valued y(j)s as:

[y(0),y(1),..,y(n/2)]        if n is even
[y(0),y(1),..,y((n-1)/2)]    if n is odd

so that things work nicely exactly as fft (as one would expect)?

What am I missing?

EDIT: the issue is being discussed here

1
That's probably (I'm guessing) because of numpy's complex number representations. What you see as two float64 makes up the complex128 data. And the final conversion is missing probably.percusse

1 Answers

1
votes

Not a good reason, but one possible reason is to match the number of independent degrees of freedom with the number of variables in the input and output of the transform function. If you output only complex vector elements from strictly real input, then Im(y(0)) and Im(y(N/2)) are always zero (for even N), and thus a complex function return would waste memory while carrying no additional information by making the output two element components larger than the input, even though the degrees of freedom should be exactly the same.

The equality of input and output vector memory sizes also allows doing an in-place RFFT without requiring any additional memory allocation, which might be important in real-time systems with constrained memory relative to the FFT size.

Whereas FFTW is more typically run on big systems where it is more common for programmers use(waste?) massive amounts of memory more than the minimum theoretically needed.