pyfftw.builders
- Get FFTW
objects using a numpy.fft
like interface¶
Overview¶
This module contains a set of functions that return
pyfftw.FFTW
objects.
The interface to create these objects is mostly the same as
numpy.fft
, only instead of the call returning the result of the
FFT, a pyfftw.FFTW
object is returned that performs that FFT
operation when it is called. Users should be familiar with
numpy.fft
before reading on.
In the case where the shape argument, s
(or n
in the
1-dimensional case), dictates that the passed-in input array be copied
into a different processing array, the returned object is an
instance of a child class of pyfftw.FFTW
,
_FFTWWrapper
, which wraps the call
method in order to correctly perform that copying. That is, subsequent
calls to the object (i.e. through
__call__()
) should occur
with an input array that can be sliced to the same size as the
expected internal array. Note that a side effect of this is that
subsequent calls to the object can be made with an array that is
bigger than the original (but not smaller).
Only the call method is wrapped; update_arrays()
still expects an array with the correct size, alignment, dtype etc for
the pyfftw.FFTW
object.
When the internal input array is bigger along any axis than the input
array that is passed in (due to s
dictating a larger size), then the
extra entries are padded with zeros. This is a one time action. If the
internal input array is then extracted using
pyfftw.FFTW.input_array
, it is possible to
persistently fill the padding space with whatever the user desires, so
subsequent calls with a new input only overwrite the values that aren’t
padding (even if the array that is used for the call is bigger than the
original - see the point above about bigger arrays being sliced to
fit).
The precision of the FFT operation is acquired from the input array. If an array is passed in that is not of float type, or is of an unknown float type, an attempt is made to convert the array to a double precision array. This results in a copy being made.
If an array of the incorrect complexity is passed in (e.g. a complex array is passed to a real transform routine, or vice-versa), then an attempt is made to convert the array to an array of the correct complexity. This results in a copy being made.
Although the array that is internal to the pyfftw.FFTW
object
will be correctly loaded with the values within the input array, it is
not necessarily the case that the internal array is the input array.
The actual internal input array can always be retrieved with
pyfftw.FFTW.input_array
.
The behavior of the norm
parameter in all builder routines matches that
of the corresponding numpy.fft
functions. In particular, if
norm == "backward"
(alias of None
) then the forward/direct FFT is
unscaled and the backward/inverse is scaled by 1/N, where N is the length of
the input array (for multidimensional FFTs it’s the product of the lengths of
each dimension). If norm == "ortho"
then both the forward and the backward
FFTs are scaled by 1/sqrt(N). Finally, if norm == "forward"
then the
forward FFT is scaled by 1/N and the backward is unscaled (exact opposite of
the "backward"
case). The default case is norm == "backward"
.
In all three cases, using the same norm
value for both the forward and the
backward FFT ensures roundtrip equality, i.e. that applying the forwad and
then the backward FFT to an input array returns the original array (up to
numerical accuracy).
Example:
>>> import pyfftw
>>> a = pyfftw.empty_aligned(4, dtype='complex128')
>>> fft = pyfftw.builders.fft(a)
>>> a[:] = [1, 2, 3, 4]
>>> fft() # returns the output
array([ 10.+0.j, -2.+2.j, -2.+0.j, -2.-2.j])
More examples can be found in the tutorial.
Supported Functions and Caveats¶
The following functions are supported. They can be used with the
same calling signature as their respective functions in
numpy.fft
or (in the case of real-to-real transforms)
scipy.fftpack
.
Standard FFTs
Real FFTs
DCTs and DSTs
The first caveat is that the dtype of the input array must match the
transform. For example, for fft
and ifft
, the dtype must
be complex, for rfft
it must be real, and so on. The other point
to note from this is that the precision of the transform matches the
precision of the input array. So, if a single precision input array is
passed in, then a single precision transform will be used.
The second caveat is that repeated axes are handled differently; with
the returned pyfftw.FFTW
object, axes that are repeated in the
axes argument are considered only once, as compared to numpy.fft
in which repeated axes results in the DFT being taken along that axes
as many times as the axis occurs (this is down to the underlying
library).
Note that unless the auto_align_input
argument to the function
is set to True
, the 'FFTW_UNALIGNED'
flag
is set in the returned pyfftw.FFTW
object. This disables some
of the FFTW optimisations that rely on aligned arrays. Also worth
noting is that the auto_align_input
flag only results in a copy
when calling the resultant pyfftw.FFTW
object if the input
array is not already aligned correctly.
Additional Arguments¶
In addition to the arguments that are present with their complementary
functions in numpy.fft
, each of these functions also offers the
following additional keyword arguments:
overwrite_input
: Whether or not the input array can be overwritten during the transform. This sometimes results in a faster algorithm being made available. It causes the'FFTW_DESTROY_INPUT'
flag to be passed to thepyfftw.FFTW
object. This flag is not offered for the multi-dimensional inverse real transforms, as FFTW is unable to not overwrite the input in that case.planner_effort
: A string dictating how much effort is spent in planning the FFTW routines. This is passed to the creation of thepyfftw.FFTW
object as an entry in the flags list. They correspond to flags passed to thepyfftw.FFTW
object.The valid strings, in order of their increasing impact on the time to compute are:
'FFTW_ESTIMATE'
,config.PLANNER_EFFORT
(default),'FFTW_PATIENT'
and'FFTW_EXHAUSTIVE'
.The Wisdom that FFTW has accumulated or has loaded (through
pyfftw.import_wisdom()
) is used during the creation ofpyfftw.FFTW
objects.threads
: The number of threads used to perform the FFT.auto_align_input
: Correctly byte align the input array for optimal usage of vector instructions. This can lead to a substantial speedup.Setting this argument to
True
makes sure that the input array is correctly aligned. It is possible to correctly byte align the array prior to calling this function (using, for example,pyfftw.byte_align()
). If and only if a realignment is necessary is a new array created. If a new array is created, it is up to the calling code to acquire that new input array usingpyfftw.FFTW.input_array
.The resultant
pyfftw.FFTW
object that is created will be designed to operate on arrays that are aligned. If the object is called with an unaligned array, this would result in a copy. Despite this, it may still be faster to set theauto_align_input
flag and incur a copy with unaligned arrays than to set up an object that uses aligned arrays.It’s worth noting that just being aligned may not be sufficient to create the fastest possible transform. For example, if the array is not contiguous (i.e. certain axes have gaps in memory between slices), it may be faster to plan a transform for a contiguous array, and then rely on the array being copied in before the transform (which
pyfftw.FFTW
will handle for you). Theauto_contiguous
argument controls whether this function also takes care of making sure the array is contiguous or not.auto_contiguous
: Make sure the input array is contiguous in memory before performing the transform on it. If the array is not contiguous, it is copied into an interim array. This is because it is often faster to copy the data before the transform and then transform a contiguous array than it is to try to take the transform of a non-contiguous array. This is particularly true in conjunction with theauto_align_input
argument which is used to make sure that the transform is taken of an aligned array.Like
auto_align_input
, If a new array is created, it is up to the calling code to acquire that new input array usingpyfftw.FFTW.input_array
.avoid_copy
: By default, these functions will always create a copy (and sometimes more than one) of the passed in input array. This is because the creation of thepyfftw.FFTW
object generally destroys the contents of the input array. Setting this argument toTrue
will try not to create a copy of the input array, likely resulting in the input array being destroyed. If it is not possible to create the object without a copy being made, aValueError
is raised.Example situations that require a copy, and so cause the exception to be raised when this flag is set:
The shape of the FFT input as dictated by
s
is necessarily different from the shape of the passed-in array.The dtypes are incompatible with the FFT routine.
The
auto_contiguous
orauto_align
flags are True and the input array is not already contiguous or aligned.
This argument is distinct from
overwrite_input
in that it only influences a copy during the creation of the object. It changes no flags in thepyfftw.FFTW
object.
The exceptions raised by each of these functions are as per their
equivalents in numpy.fft
, or as documented above.
The Functions¶
- pyfftw.builders.dct(a, n=None, axis=- 1, overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, type=2)¶
Return a
pyfftw.FFTW
object representing a 1D DCT.The first three arguments and ‘type’ are as per
scipy.fftpack.dct()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.dst(a, n=None, axis=- 1, overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, type=2)¶
Return a
pyfftw.FFTW
object representing a 1D DST.The first three arguments and ‘type’ are as per
scipy.fftpack.dst()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.fft(a, n=None, axis=- 1, overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing a 1D FFT.The first three arguments are as per
numpy.fft.fft()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.fft2(a, s=None, axes=(- 2, - 1), overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing a 2D FFT.The first three arguments are as per
numpy.fft.fft2()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.fftn(a, s=None, axes=None, overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing a n-D FFT.The first three arguments are as per
numpy.fft.fftn()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.ifft(a, n=None, axis=- 1, overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing a 1D inverse FFT.The first three arguments are as per
numpy.fft.ifft()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.ifft2(a, s=None, axes=(- 2, - 1), overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing a 2D inverse FFT.The first three arguments are as per
numpy.fft.ifft2()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.ifftn(a, s=None, axes=None, overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing an n-D inverse FFT.The first three arguments are as per
numpy.fft.ifftn()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.irfft(a, n=None, axis=- 1, overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing a 1D real inverse FFT.The first three arguments are as per
numpy.fft.irfft()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.irfft2(a, s=None, axes=(- 2, - 1), planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing a 2D real inverse FFT.The first three arguments are as per
numpy.fft.irfft2()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.irfftn(a, s=None, axes=None, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing an n-D real inverse FFT.The first three arguments are as per
numpy.fft.rfftn()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.rfft(a, n=None, axis=- 1, overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing a 1D real FFT.The first three arguments are as per
numpy.fft.rfft()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.rfft2(a, s=None, axes=(- 2, - 1), overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing a 2D real FFT.The first three arguments are as per
numpy.fft.rfft2()
; the rest of the arguments are documented in the module docs.
- pyfftw.builders.rfftn(a, s=None, axes=None, overwrite_input=False, planner_effort=None, threads=None, auto_align_input=True, auto_contiguous=True, avoid_copy=False, norm=None)¶
Return a
pyfftw.FFTW
object representing an n-D real FFT.The first three arguments are as per
numpy.fft.rfftn()
; the rest of the arguments are documented in the module docs.