Description
I ran into this issue with numpy 1.15.4 when some existing code (that was very robust and working fine) started to give crazy results, and I isolated it to np.fft.rfftn. I'm actually hoping that I'm just doing something stupid, but I can't find an error in my logic so far.
Since it's non-trivial to create on-the-fly example data for this, I've made some test data available in a npy file here (simulated ocean waves). The following code illustrates the issue - I have a cube of data which represents a simulated wave field in 3D (Time, X, Y). I am trying to make a PSD. Because the input data are real, I'm using rfftn. So, I want to perform the full complex FFT along axes 1 and 2 and the conjugate symmetric FFT along axis 0.
Reproducing code example:
import numpy as np
import numpy.fft as nfft
import matplotlib.pyplot as plt
with open('waves.npy', 'rb') as fid:
waves = np.load(fid)
goodn = nfft.rfftn(waves.T)
good1 = nfft.rfft(waves, axis=0)
goodn1 = nfft.rfftn(waves, axes=[0])
goodn3 = nfft.rfftn(waves.T, axes=[0,1,2])
fig, axs = plt.subplots(figsize=(8,8), ncols=2, nrows=2)
axs[0][0].imshow(np.ma.log10(np.abs(goodn[0,:,:])**2), aspect='auto')
axs[1][0].imshow(np.ma.log10(np.abs(good1[0,:,:])**2), aspect='auto')
axs[1][1].imshow(np.ma.log10(np.abs(goodn1[0,:,:])**2), aspect='auto')
axs[0][1].imshow(np.ma.log10(np.abs(goodn3[0,:,:])**2), aspect='auto')
All of the above actually produces plots that are correct. In the top two plots in the image below, you can see the deep water dispersion curve.
If I transpose my data so the 'real' axis that I want to use is the last axis and use rfftn out of the box, it works - "goodn", upper left. If I do the same thing but specify all 3 axes (without changing the order), it also works - "goodn3", upper right. If I use rfft and specify axis=0, instead of using rfftn, I get junk because I haven't taken the transform of the X and Y dimensions - "good1", lower left. If I do essentially the equivalent by using rfftn but only specifying axes=[0], I get the same exact junk - "goodn1", lower right.
Error message:
However, what I had been doing, and what I want to do, and from the docs I think I should be able to do, is this:
realgood = nfft.rfftn(waves, axes=[1,2,0])
In an older version of numpy (at least up to 1.13), that worked perfectly. In numpy 1.15.4, that gave me the kind of junk described above. It looked like the X and Y axes were not actually being transformed (full complex transform) like they should be. I thought I might get around it by upgrading to 1.16.2 ... however now what that does is give me this error:
Traceback (most recent call last):
File "<ipython-input-11-3dad548cb9e8>", line 1, in <module>
runfile('C:/Users/asmith/Documents/Git/python_utils/scripts/gist.py', wdir='C:/Users/asmith/Documents/Git/python_utils/scripts')
File "C:\Users\asmith\AppData\Local\Continuum\anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 786, in runfile
execfile(filename, namespace)
File "C:\Users\asmith\AppData\Local\Continuum\anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/asmith/Documents/Git/python_utils/scripts/gist.py", line 57, in <module>
realgood = nfft.rfftn(waves, axes=[1,2,0])
File "C:\Users\asmith\AppData\Local\Continuum\anaconda3\lib\site-packages\mkl_fft\_numpy_fft.py", line 1043, in rfftn
output = mkl_fft.rfftn_numpy(a, s, axes)
File "mkl_fft\_pydfti.pyx", line 947, in mkl_fft._pydfti.rfftn_numpy
File "mkl_fft\_pydfti.pyx", line 846, in mkl_fft._pydfti._fftnd_impl
File "mkl_fft\_pydfti.pyx", line 724, in mkl_fft._pydfti._iter_fftnd
File "mkl_fft\_pydfti.pyx", line 667, in mkl_fft._pydfti._init_nd_shape_and_axes
ValueError: all axes must be unique
If I switch the two spatial axes (which should be the same, yes? Axes 1 and 2 are the same size), I get a different error:
realgood = nfft.rfftn(waves, axes=[2,1,0])
gives me this:
Traceback (most recent call last):
File "<ipython-input-15-3dad548cb9e8>", line 1, in <module>
runfile('C:/Users/asmith/Documents/Git/python_utils/scripts/gist.py', wdir='C:/Users/asmith/Documents/Git/python_utils/scripts')
File "C:\Users\asmith\AppData\Local\Continuum\anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 786, in runfile
execfile(filename, namespace)
File "C:\Users\asmith\AppData\Local\Continuum\anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/asmith/Documents/Git/python_utils/scripts/gist.py", line 57, in <module>
realgood = nfft.rfftn(waves, axes=[2,1,0])
File "C:\Users\asmith\AppData\Local\Continuum\anaconda3\lib\site-packages\mkl_fft\_numpy_fft.py", line 1043, in rfftn
output = mkl_fft.rfftn_numpy(a, s, axes)
File "mkl_fft\_pydfti.pyx", line 951, in mkl_fft._pydfti.rfftn_numpy
ValueError: could not broadcast input array from shape (512,64) into shape (512,512)
Numpy/Python version information:
1.16.2 3.7.3 (default, Mar 27 2019, 17:13:21) [MSC v.1915 64 bit (AMD64)]