I am fairly new to coding but have been put on a project where i am using 'numpy.fft.fftn' for cross correlation. Most of this work is from translating Matlab code over. This is the part of code that I am having trouble with:
def rot90_3D(T):
T=numpy.flip(numpy.flip(numpy.flip(T,0),1),2);
return(T)
T_size = [T.shape[0],T.shape[1],T.shape[2]]; I_size = [I.shape[0],I.shape[1],I.shape[2]];
TI=[]
for i in range(0,3,1):
TI1=T_size[i] I_size[i]
TI=numpy.append(TI,TI1)
one=numpy.ones((1,3))
outsize = TI - one;
FT = numpy.fft.fftn(rot90_3D(T),outsize);
When I run this cell cell with my input of T being an array of float32 which is (51,51,51) and the values are all between 0 and 1, most of them being decimals something like 0.131866. Yet when I run the cell I get this error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Please let me know what I can do to fix this.
EDIT: Here is the full error message:
Traceback (most recent call last):
File "C:\Users\Grant\OneDrive\Desktop\SearchParticle Test.py", line 53, in <module>
FT = numpy.fft.fftn(T2,outsize);
File "<__array_function__ internals>", line 5, in fftn
File "C:\Users\Grant\anaconda3\lib\site-packages\numpy\fft\_pocketfft.py", line 813, in fftn
return _raw_fftnd(a, s, axes, fft, norm)
File "C:\Users\Grant\anaconda3\lib\site-packages\numpy\fft\_pocketfft.py", line 705, in _raw_fftnd
a = function(a, n=s[ii], axis=axes[ii], norm=norm)
File "<__array_function__ internals>", line 5, in fft
File "C:\Users\Grant\anaconda3\lib\site-packages\numpy\fft\_pocketfft.py", line 214, in fft
inv_norm = _get_forward_norm(n, norm)
File "C:\Users\Grant\anaconda3\lib\site-packages\numpy\fft\_pocketfft.py", line 79, in _get_forward_norm
if n < 1:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
CodePudding user response:
In [94]: T = np.random.rand(10,10,10)
A more direct way of flipping T
:
In [95]: t1 = rot90_3D(T)
In [96]: t2 = T[::-1,::-1,::-1]
In [97]: np.allclose(t1,t2)
Out[97]: True
For your outsize
:
In [98]: I = np.ones((3,3,3)) # sample
In [99]: T_size = [T.shape[0],T.shape[1],T.shape[2]]; I_size = [I.shape[0],I.shape[1],I.shape[2]];
...: TI=[]
...: for i in range(0,3,1):
...: TI1=T_size[i] I_size[i]
...: TI=numpy.append(TI,TI1)
...: one=numpy.ones((1,3))
...: outsize = TI - one;
In [100]: outsize
Out[100]: array([[12., 12., 12.]])
In [101]: T.shape, I.shape
Out[101]: ((10, 10, 10), (3, 3, 3))
Just do:
In [102]: np.array(T.shape) np.array(I.shape)-1
Out[102]: array([12, 12, 12])
T.shape
is a tuple; your T_size
is a list version of that. Arrays can be added without iteration.
But a list comprehension also does nicely:
In [104]: [i j-1 for i,j in zip(T.shape, I.shape)]
Out[104]: [12, 12, 12]
So far no error. So the problem must be in the fft
call.
Here's the full error that you should have shown:
In [105]: numpy.fft.fftn(rot90_3D(T),outsize)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [105], in <cell line: 1>()
----> 1 numpy.fft.fftn(rot90_3D(T),outsize)
File <__array_function__ internals>:5, in fftn(*args, **kwargs)
File ~\anaconda3\lib\site-packages\numpy\fft\_pocketfft.py:815, in fftn(a, s, axes, norm)
715 @array_function_dispatch(_fftn_dispatcher)
716 def fftn(a, s=None, axes=None, norm=None):
717 """
718 Compute the N-dimensional discrete Fourier Transform.
719
(...)
813
814 """
--> 815 return _raw_fftnd(a, s, axes, fft, norm)
File ~\anaconda3\lib\site-packages\numpy\fft\_pocketfft.py:707, in _raw_fftnd(a, s, axes, function, norm)
705 itl.reverse()
706 for ii in itl:
--> 707 a = function(a, n=s[ii], axis=axes[ii], norm=norm)
708 return a
File <__array_function__ internals>:5, in fft(*args, **kwargs)
File ~\anaconda3\lib\site-packages\numpy\fft\_pocketfft.py:214, in fft(a, n, axis, norm)
212 if n is None:
213 n = a.shape[axis]
--> 214 inv_norm = _get_forward_norm(n, norm)
215 output = _raw_fft(a, n, axis, False, True, inv_norm)
216 return output
File ~\anaconda3\lib\site-packages\numpy\fft\_pocketfft.py:79, in _get_forward_norm(n, norm)
78 def _get_forward_norm(n, norm):
---> 79 if n < 1:
80 raise ValueError(f"Invalid number of FFT data points ({n}) specified.")
82 if norm is None or norm == "backward":
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Tracing this will take some work, but at the core it's testing n
. n
should be a number, but for some reason it's an array. What is that n
?
I haven't used fft
, so am not familiar with the required arguments.
But if I call it with without the outsize
, I get a result
In [109]: f = numpy.fft.fftn(rot90_3D(T))
In [110]: f.shape
Out[110]: (10, 10, 10)
So there's something wrong with the way you calculate outsize
. When you got the error, did you (re)read the fftn
docs - to make sure you use the right arguments?
Glancing at the docs, I deduced that outsize
could be a simple list of 3 numbers:
In [111]: f = numpy.fft.fftn(rot90_3D(T), [12,12,12])
In [112]: f.shape
Out[112]: (12, 12, 12)
np.array([12,12,12])
is also ok. But a (1,3) array np.array([[12,12,12]])
produces the error.
When translating MATLAB code, don't try to make everything 2d. numpy
arrays can be 1d, and in some cases must be.