Fourier Transform and Convolution¶
This module provides some functions to compute fourier transform, convolution and correlation numerically.
Fourier transform¶
These functions compute fourier transform or its inverse for signals
defined on an interval or region which is symmetric w.r.t. the origin.
They differ from vanilla Discrete Fourier Transform (DFT) provided by
torch.fft
in that correct scale and shift are considered and
thus serve as numerical approximation to continuous fourier transform.
For example, the function ft1()
computes the 1D Fourier transform of signal
\(f\). Given signal length \(N\), assuming \(f[k]\) represents sampled values on
points \(\{k\delta_f\}_{k=-\lfloor N/2\rfloor}^{\lfloor(N-1)/2\rfloor}\)
where \(\delta_f\) is sampling interval, then ft1()
computes
where \(\delta_h=1/(N\delta_f)\) is sampling interval in frequency domain.
Indices \(-\lfloor\frac{N}{2}\rfloor, \cdots,\lfloor\frac{N-1}{2}\rfloor\)
for \(k\) and \(l\) correspond to 0
, …, N-1
in the given array.
In other words, this function works like
>>> from torch.fft import fft, fftshift, ifftshift
>>>
>>> f = torch.rand(9)
>>> h1 = ft1(f, 0.1)
>>> h2 = fftshift(fft(ifftshift(f))) * 0.1
>>> torch.allclose(h1, h2)
True
Multiplication with sampling interval is necessary if consistent scale
with continuous Fourier transform is desired, which is called DFT-scale.
Otherwise, it can be set to None
.
The following example illustrates its approximation to continuous Fourier transform, as well as its precision in a simple occasion for 32-bit float.
>>> x = dnois.utils.interval(1000, 4e-3) # [-2, 2]
>>> y = torch.exp(-torch.pi * x.square()) # Gaussian function
>>> fx = dnois.utils.interval(1000, 0.25) # frequency
>>> g = torch.exp(-torch.pi * fx.square()) # ground truth spectrum
>>> torch.allclose(ft1(y, 4e-3).real, g, atol=1e-6)
True
Note
The sampling interval (like delta
argument for ft1()
) will be
multiplied to transformed signal if given, so it can be a float
or a tensor with shape broadcastable to original signal. But if it is not a
0D tensor, its size on the dimensions to be transformed must be 1.
Convolution¶
These functions compute convolution between two signals f1
and f2
.
dconv()
computes discrete convolution.
Numerical optimization and correct scale are considered
in conv()
so it serve as a numerical approximation to continuous convolution.
>>> f1, f2 = torch.tensor([1., 2., 3., 4.]), torch.tensor([1., 2., 3.])
>>> g_full_linear = torch.tensor([1., 4., 10., 16., 17., 12.])
>>> torch.allclose(dconv(f1, f2), g_full_linear)
True
>>> g_same_linear = torch.tensor([4., 10., 16., 17.])
>>> torch.allclose(dconv(f1, f2, out='same'), g_same_linear)
True
>>> g_full_circular = torch.tensor([18., 16., 10., 16.])
>>> torch.allclose(dconv(f1, f2, padding='none'), g_full_circular)
True
>>> f1, f2 = torch.rand(5), torch.rand(6)
>>> torch.allclose(conv(f1, f2, spacing=0.1), dconv(f1, f2) * 0.1)
True
Note
If all the signals involved is real-valued, set real
to True
to improve
the computation and return a real-valued tensor.
|
Computes continuous convolution for two tensors \(f_1\) and \(f_2\) utilizing FFT. |
|
1D version of |
|
2D version of |
|
Computes n-D discrete convolution for two tensors \(f_1\) and \(f_2\) utilizing FFT. |
|
1D version of |
|
2D version of |
Multiple convolutions¶
Sometimes one may need to compute convolutions between a group of tensors and a single common tensor. In that case, it is sensible to compute the Fourier transform of the common tensor only once. The following functions serve for this purpose.
|
Discrete version of |
|
Discrete version of |
|
Discrete version of |
|
Compute the convolutions between each signal in |
|
See |
|
See |