API
In the following, you find the documentation of some, and hopefully soon all, exported functions of the NFFT.jl package family:
AbstractNFFTs.AbstractComplexFTPlan
AbstractNFFTs.AbstractFTPlan
AbstractNFFTs.AbstractNFCTPlan
AbstractNFFTs.AbstractNFFTPlan
AbstractNFFTs.AbstractNFSTPlan
AbstractNFFTs.AbstractNNFFTPlan
AbstractNFFTs.AbstractRealFTPlan
AbstractNFFTs.accuracyParams
AbstractNFFTs.nfct
AbstractNFFTs.nfct_transpose
AbstractNFFTs.nfft
AbstractNFFTs.nfft_adjoint
AbstractNFFTs.nfst
AbstractNFFTs.nfst_transpose
AbstractNFFTs.nodes!
AbstractNFFTs.plan_nfft
AbstractNFFTs.size_in
AbstractNFFTs.size_out
NFFTTools.calculateToeplitzKernel
NFFTTools.calculateToeplitzKernel!
NFFTTools.convolveToeplitzKernel!
AbstractNFFTs.AbstractComplexFTPlan
— TypeAbstractComplexFTPlan{T,D,R}
Abstract type for either an NFFT plan or an NNFFT plan.
- T is the element type (Float32/Float64)
- D is the number of dimensions of the input array.
- R is the number of dimensions of the output array.
AbstractNFFTs.AbstractFTPlan
— TypeAbstractFTPlan{T,D,R}
Abstract type for any NFFT-like plan (NFFT, NFFT, NFCT, NFST).
- T is the element type (Float32/Float64)
- D is the number of dimensions of the input array.
- R is the number of dimensions of the output array.
AbstractNFFTs.AbstractNFCTPlan
— TypeAbstractNFCTPlan{T,D,R}
Abstract type for an NFCT plan.
- T is the element type (Float32/Float64)
- D is the number of dimensions of the input array.
- R is the number of dimensions of the output array.
AbstractNFFTs.AbstractNFFTPlan
— TypeAbstractNFFTPlan{T,D,R}
Abstract type for an NFFT plan.
- T is the element type (Float32/Float64)
- D is the number of dimensions of the input array.
- R is the number of dimensions of the output array.
AbstractNFFTs.AbstractNFSTPlan
— TypeAbstractNFSTPlan{T,D,R}
Abstract type for an NFST plan.
- T is the element type (Float32/Float64)
- D is the number of dimensions of the input array.
- R is the number of dimensions of the output array.
AbstractNFFTs.AbstractNNFFTPlan
— TypeAbstractNNFFTPlan{T,D,R}
Abstract type for an NNFFT plan.
- T is the element type (Float32/Float64)
- D is the number of dimensions of the input array.
- R is the number of dimensions of the output array.
AbstractNFFTs.AbstractRealFTPlan
— TypeAbstractRealFTPlan{T,D,R}
Abstract type for either an NFCT plan or an NFST plan.
- T is the element type (Float32/Float64)
- D is the number of dimensions of the input array.
- R is the number of dimensions of the output array.
AbstractNFFTs.accuracyParams
— MethodaccuracyParams(; [m, σ, reltol]) -> m, σ, reltol
Calculate accuracy parameters m, σ, reltol based on either
- reltol
or
- m, σ
TODO: Right now, the oversampling parameter is not taken into account, i.e. σ=2.0 is assumed
AbstractNFFTs.nfct
— Methodnfft(k, f, rest...; kwargs...)
calculates the nfft of the array f
for the nodes contained in the matrix k
The output is a vector of length M=size(nodes,2)
AbstractNFFTs.nfct_transpose
— Methodnfft_adjoint(k, N, fHat, rest...; kwargs...)
calculates the adjoint nfft of the vector fHat
for the nodes contained in the matrix k
. The output is an array of size N
AbstractNFFTs.nfft
— Methodnfft(k, f, rest...; kwargs...)
calculates the nfft of the array f
for the nodes contained in the matrix k
The output is a vector of length M=size(nodes,2)
AbstractNFFTs.nfft_adjoint
— Methodnfft_adjoint(k, N, fHat, rest...; kwargs...)
calculates the adjoint nfft of the vector fHat
for the nodes contained in the matrix k
. The output is an array of size N
AbstractNFFTs.nfst
— Methodnfft(k, f, rest...; kwargs...)
calculates the nfft of the array f
for the nodes contained in the matrix k
The output is a vector of length M=size(nodes,2)
AbstractNFFTs.nfst_transpose
— Methodnfft_adjoint(k, N, fHat, rest...; kwargs...)
calculates the adjoint nfft of the vector fHat
for the nodes contained in the matrix k
. The output is an array of size N
AbstractNFFTs.nodes!
— Methodnodes!(p, k) -> p
Change nodes k
in the plan p
operation and return the plan.
AbstractNFFTs.size_in
— Methodsize_in(p)
Size of the input array for the plan p (NFFT/NFCT/NFST/NNFFT). The returned tuple has R
entries. Note that this will be the output size for the transposed / adjoint operator.
AbstractNFFTs.size_out
— Methodsize_out(p)
Size of the output array for the plan p (NFFT/NFCT/NFST/NNFFT). The returned tuple has R
entries. Note that this will be the input size for the transposed / adjoint operator.
Base.:*
— Method *(p, f) -> fHat
For a non-directional D
dimensional plan p
this calculates the NFFT/NNFFT of a D
dimensional array f
of size N
. fHat
is a vector of length M
. (M
and N
are defined in the plan creation)
For a directional D
dimensional plan p
both f
and fHat
are D
dimensional arrays, and the dimension specified in the plan creation is affected.
Base.:*
— Method *(p, f) -> fHat
For a non-directional D
dimensional plan p
this calculates the NFCT/NFST of a D
dimensional array f
of size N
. fHat
is a vector of length M
. (M
and N
are defined in the plan creation)
For a directional D
dimensional plan p
both f
and fHat
are D
dimensional arrays, and the dimension specified in the plan creation is affected.
LinearAlgebra.mul!
— Methodmul!(fHat, p, f) -> fHat
Inplace NFFT/NFCT/NFST/NNFFT transforming the D
dimensional array f
to the R
dimensional array fHat
. The transformation is applied along D-R+1
dimensions specified in the plan p
.
LinearAlgebra.mul!
— Methodmul!(f, p, fHat) -> f
Inplace adjoint NFFT/NNFFT transforming the R
dimensional array fHat
to the D
dimensional array f
. The transformation is applied along D-R+1
dimensions specified in the plan p
.
LinearAlgebra.mul!
— Methodmul!(f, p, fHat) -> f
Inplace transposed NFCT/NFST transforming the R
dimensional array fHat
to the D
dimensional array f
. The transformation is applied along D-R+1
dimensions specified in the plan p
.
AbstractNFFTs.plan_nfft
— Method plan_nfft(k::Matrix{T}, N::NTuple{D,Int}, rest...; kargs...)
compute a plan for the NFFT of a size-N
array at the nodes contained in k
.
NFFT.precomputeLinInterp
— MethodPrecompute the look up table for the window function φ.
Remarks:
- Only the positive half is computed
- The window is computed for the interval [0, (m)/Ñ]. The reason for the +2 is that we do evaluate the window function outside its interval, since x does not necessary match the sampling points
- The window has K+1 entries and during the index calculation we multiply with the factor K/(m).
- It is very important that K/(m) is an integer since our index calculation exploits this fact. We therefore always use
Int(K/(m))
instead ofK÷(m)
since this gives an error while the later variant would silently error.
NFFTTools.calculateToeplitzKernel!
— MethodcalculateToeplitzKernel!(f::Array{Complex{T}}, p::AbstractNFFTPlan, tr::Matrix{T}, fftplan)
Calculate the kernel for an implementation of the Gram matrix that utilizes its Toeplitz structure and writes it in-place in f
, which has to be twice the size of the desired image matrix, as the Toeplitz trick requires an oversampling factor of 2 (cf. Wajer, F. T. A. W., and K. P. Pruessmann. "Major speedup of reconstruction for sensitivity encoding with arbitrary trajectories." Proc. Intl. Soc. Mag. Res. Med. 2001.). The type of the kernel f
has to be Complex{T}
, i.e. the complex of the k-space trajectory's type; for speed and memory efficiecy, call this function with Float32.(tr)
, and set the type of f
accordingly.
Required Arguments
f::Array{T}
: Array in which the kernel will be written.p::AbstractNFFTPlan
: NFFTPlan with the same dimensions astr
, which will be overwritten in place.tr::Matrix{T}
: non-Cartesian k-space trajectory in units revolutions/voxel, i.e.tr[i] ∈ [-0.5, 0.5] ∀ i
. The matrix has the size2 x Nsamples
for 2D imaging with a trajectory lengthNsamples
, and3 x Nsamples
for 3D imaging.fftplan
: plan for the final FFT of the kernel from image to k-space. Therefore, it has to have twice the size of the original image. Calculate, e.g., withfftplan = plan_fft(zeros(Complex{T}, 2 .* shape); flags=FFTW.MEASURE)
, whereshape
is the size of the reconstructed image.
Examples
julia> using FFTW
julia> Nx = 32;
julia> trj = Float32.(rand(2, 1000) .- 0.5);
julia> p = plan_nfft(trj, (2Nx,2Nx))
NFFTPlan with 1000 sampling points for an input array of size(64, 64) and an output array of size(1000,) with dims 1:2
julia> fftplan = plan_fft(zeros(ComplexF32, (2Nx,2Nx)); flags=FFTW.MEASURE);
julia> λ = Array{ComplexF32}(undef, 2Nx, 2Nx);
julia> calculateToeplitzKernel!(λ, p, trj, fftplan);
julia> y = randn(ComplexF32, Nx, Nx);
julia> convolveToeplitzKernel!(y, λ);
NFFTTools.calculateToeplitzKernel
— MethodcalculateToeplitzKernel(shape, tr::Matrix{T}[; m = 4, σ = 2.0, window = :kaiser_bessel, fftplan = plan_fft(zeros(Complex{T}, 2 .* shape); flags=FFTW.ESTIMATE), kwargs...])
Calculate the kernel for an implementation of the Gram matrix that utilizes its Toeplitz structure. The output is an array of twice the size of shape
, as the Toeplitz trick requires an oversampling factor of 2 (cf. Wajer, F. T. A. W., and K. P. Pruessmann. "Major speedup of reconstruction for sensitivity encoding with arbitrary trajectories." Proc. Intl. Soc. Mag. Res. Med. 2001.). The type of the kernel is Complex{T}
, i.e. the complex of the k-space trajectory's type; for speed and memory efficiency, call this function with Float32.(tr)
, and the kernel will also be Float32
.
Required Arguments
shape::NTuple(Int)
: size of the image; e.g.(256, 256)
for 2D imaging, or(256,256,128)
for 3D imagingtr::Matrix{T}
: non-Cartesian k-space trajectory in units revolutions/voxel, i.e.tr[i] ∈ [-0.5, 0.5] ∀ i
. The matrix has the size2 x Nsamples
for 2D imaging with a trajectory lengthNsamples
, and3 x Nsamples
for 3D imaging.
Optional Arguments:
m::Int
: nfft kernel size (used to calculate the Toeplitz kernel);default = 4
σ::Number
: nfft oversampling factor during the calculation of the Toeplitz kernel;default = 2
Keyword Arguments:
fftplan
: plan for the final FFT of the kernel from image to k-space. Therefore, it has to have twice the size of the original image.default = plan_fft(zeros(Complex{T}, 2 .* shape); flags=FFTW.ESTIMATE)
. If this constructor is used many times, it is worth to precompute the plan withplan_fft(zeros(Complex{T}, 2 .* shape); flags=FFTW.MEASURE)
and reuse it.kwargs
: Passed on toplan_fft!
viaNFFTPlan
; can be used to modify the flagsflags=FFTW.ESTIMATE, timelimit=Inf
.
Examples
julia> Nx = 32;
julia> trj = Float32.(rand(2, 1000) .- 0.5);
julia> λ = calculateToeplitzKernel((Nx, Nx), trj)
64×64 Matrix{ComplexF32}:
-432.209+297.833im 271.68-526.348im … 3044.35+34.6322im
990.057-244.569im -582.825+473.084im 45.7631-87.8965im
1922.01+223.525im 9248.63-452.04im 3649.78+108.941im
-402.371-3.37619im 496.815+231.891im 322.646-329.089im
-482.346-121.534im 559.756-106.981im 155.183+454.0im
3293.8+194.388im -3361.43+34.1272im … 2672.16-526.853im
-936.331+172.246im 4394.11-400.762im -1121.04+160.219im
-135.828+169.448im 3509.17+59.0678im 3883.84-501.913im
395.143+158.638im 24.4377-387.153im 5731.3+173.827im
925.902-117.765im 2935.3+346.28im -1414.12-214.701im
⋮ ⋱
2239.72-295.883im 490.442+524.399im … 2028.84-36.5824im
-1108.11+227.146im 24.7403-455.661im -549.699+105.319im
1323.78+110.713im -321.052+117.802im 651.944-443.178im
-52.1597+288.0im -326.042-516.516im 3619.1+44.4651im
1180.56+73.3666im -26.1233+155.148im -869.065-405.832im
3555.36+649.527im -198.245-878.042im … 1198.83-317.062im
-368.958-177.954im -360.343+406.469im -1478.96-154.512im
4861.29+38.9623im 6082.55-267.478im 2519.09+293.503im
1022.55-185.869im 177.426+414.384im 3650.56-146.597im
julia> y = randn(ComplexF32, Nx, Nx);
julia> convolveToeplitzKernel!(y, λ)
32×32 Matrix{ComplexF32}:
177.717-52.0493im 10.6059+20.7185im … 746.131+330.005im
-311.858+988.219im -1216.83-1295.14im 410.732+751.925im
-1082.27+872.968im 1023.97-1556.45im -923.699+478.63im
-999.035-525.161im -1694.59-658.558im -521.044+607.005im
-342.999+1481.82im -1729.18-2712.81im 56.5212+1394.81im
-1187.65-1979.55im 1389.67+970.033im … 2968.93-744.264im
-666.533+485.511im -1315.83+409.855im -610.146+132.258im
1159.57+64.6059im -299.169-569.622im 663.802+396.827im
-795.112-1464.63im -462.43+2442.77im -1622.72+1701.27im
-1047.67+31.5578im -1127.65-936.043im 474.071+797.911im
⋮ ⋱
327.345+2191.71im -904.635+558.786im -1449.32-276.721im
-1047.2-71.362im 363.109+567.346im -1974.0-2348.36im
-1540.45+1661.77im 1175.75+1279.75im … 1110.61+653.234im
-526.832-435.297im -265.021-2019.08im 68.5607-323.086im
-1076.52-2719.16im -477.005+2232.06im -155.59-1275.66im
1143.76-735.966im -380.489+2485.78im 1812.17-261.191im
1685.44-1243.29im 1911.16-1157.72im -991.639-42.8214im
1054.11-1282.41im 66.9358-588.991im … -952.238+1026.35im
-417.276-273.367im -946.698+1971.77im -890.339-882.05im
NFFTTools.convolveToeplitzKernel!
— MethodconvolveToeplitzKernel!(y::Array{T,N}, λ::Array{T,N}[, fftplan = plan_fft(λ; flags=FFTW.ESTIMATE), ifftplan = plan_ifft(λ; flags=FFTW.ESTIMATE), xOS1 = similar(λ), xOS2 = similar(λ)])
Convolves the image y
with the Toeplitz kernel λ
and overwrites y
with the result. y
is also returned for convenience. As this function is commonly applied many times, it is highly recommended to pre-allocate / pre-compute all optional arguments. By doing so, this entire function is non-allocating.
Required Arguments
y::Array{T,N}
: Input image that will be overwritten with the result.y
is a matrix (N=2
) for 2D imaging and a 3D tensor (N=3
) for 3D imaging. The type of the elementsT
must match the ones ofλ
.λ::Array{T,N}
: Toeplitz kernel, which as to be the same type ask
, but twice the size due to the required oversampling (cf.calculateToeplitzKernel
).
Optional, but highly recommended Arguments
fftplan
: plan for the oversampled FFT, i.e. it has to have twice the size of the original image. Calculate, e.g., withfftplan = plan_fft(λ; flags=FFTW.MEASURE)
, whereshape
is the size of the reconstructed image.ifftplan
: plan for the oversampled inverse FFT. Calculate, e.g., withifftplan = plan_ifft(λ; flags=FFTW.MEASURE)
, whereshape
is the size of the reconstructed image.xOS1
: pre-allocated array of the size ofλ
. Pre-allocate withxOS1 = similar(λ)
.xOS2
: pre-allocated array of the size ofλ
. Pre-allocate withxOS2 = similar(λ)
.
Examples
julia> using FFTW
julia> Nx = 32;
julia> trj = Float32.(rand(2, 1000) .- 0.5);
julia> λ = calculateToeplitzKernel((Nx, Nx), trj);
julia> xOS1 = similar(λ);
julia> xOS2 = similar(λ);
julia> fftplan = plan_fft(xOS1; flags=FFTW.MEASURE);
julia> ifftplan = plan_ifft(xOS1; flags=FFTW.MEASURE);
julia> y = randn(ComplexF32, Nx, Nx);
julia> convolveToeplitzKernel!(y, λ, fftplan, ifftplan, xOS1, xOS2)
32×32 Matrix{ComplexF32}:
177.717-52.0493im 10.6059+20.7185im … 746.131+330.005im
-311.858+988.219im -1216.83-1295.14im 410.732+751.925im
-1082.27+872.968im 1023.97-1556.45im -923.699+478.63im
-999.035-525.161im -1694.59-658.558im -521.044+607.005im
-342.999+1481.82im -1729.18-2712.81im 56.5212+1394.81im
-1187.65-1979.55im 1389.67+970.033im … 2968.93-744.264im
-666.533+485.511im -1315.83+409.855im -610.146+132.258im
1159.57+64.6059im -299.169-569.622im 663.802+396.827im
-795.112-1464.63im -462.43+2442.77im -1622.72+1701.27im
-1047.67+31.5578im -1127.65-936.043im 474.071+797.911im
⋮ ⋱
327.345+2191.71im -904.635+558.786im -1449.32-276.721im
-1047.2-71.362im 363.109+567.346im -1974.0-2348.36im
-1540.45+1661.77im 1175.75+1279.75im … 1110.61+653.234im
-526.832-435.297im -265.021-2019.08im 68.5607-323.086im
-1076.52-2719.16im -477.005+2232.06im -155.59-1275.66im
1143.76-735.966im -380.489+2485.78im 1812.17-261.191im
1685.44-1243.29im 1911.16-1157.72im -991.639-42.8214im
1054.11-1282.41im 66.9358-588.991im … -952.238+1026.35im
-417.276-273.367im -946.698+1971.77im -890.339-882.05im