Gnufft¶
template <typename T1> class Gnufft
Non-uniform Fast Fourier Transform operator using Kaiser-Bessel gridding.
Implements an efficient NUFFT via convolution with a Kaiser-Bessel (KB) kernel onto an oversampled Cartesian grid, followed by an FFT. Supports both CPU and GPU execution (via OpenACC or Apple Metal). An LUT (look-up table) is used for fast kernel evaluation.
Forward algorithm (image → k-space):
graph LR
A["$$\mathbf{x}$$ (image)"] --> B["$$\mathbf{x} / \hat{\kappa}$$ (deapodize)"]
B --> C["Zero-pad to $$N \cdot \text{gridos}$$"]
C --> D["FFT"]
D --> E["$$\kappa$$ interpolation"]
E --> F["$$\mathbf{d}$$ (k-space)"]
Adjoint algorithm (k-space → image):
graph RL
G["$$\mathbf{d}$$ (k-space)"] --> H["$$\kappa$$ gridding"]
H --> I["IFFT"]
I --> J["Crop to $$N$$"]
J --> K["$$/ \hat{\kappa}$$ (deapodize)"]
K --> L["$$\hat{\mathbf{x}}$$ (image)"]
Density compensation: Non-uniform k-space sampling requires density compensation weights (DCF) to correct for variable sampling density. The Pipe iterative algorithm computes these weights using the gridding/degridding pair:
where \(G^H G\) is the forward-then-adjoint gridding operation. This is
implemented in griddingSupport.h via calc3DDensityCompensation().
See : Pipe & Menon, "Sampling Density Compensation in MRI," MRM, 1999. https://doi.org/10.1002/(SICI)1522-2594(199901)41:1<179::AID-MRM25>3.0.CO;2-V
The Kaiser-Bessel kernel is:
for \(|u| \leq W/2\), zero otherwise. \(W\) is the kernel width (kernelWidth),
\(\beta\) is the shape parameter, and \(I_0\) is the modified Bessel function
of the first kind.
Parameter guidance:
- gridos (grid oversampling factor): typically 2.0. Higher values reduce
aliasing artifacts at the cost of memory and computation.
- beta is computed automatically from gridos and kernelWidth to
minimize the worst-case interpolation error.
k-space coordinates must lie within \([-N/2, N/2)\) in each dimension.
Use G * x for the forward transform and G / d for the adjoint.
See : Gdft for the exact (but slower) field-corrected DFT.
See : gridding.h for the low-level gridding and degridding routines.
See : Jackson et al., "Selection of a Convolution Function for Fourier Inversion Using Gridding," IEEE TMI, 1991. https://doi.org/10.1109/42.75611
See : Pipe & Menon, "Sampling Density Compensation in MRI," MRM, 1999. https://doi.org/10.1002/(SICI)1522-2594(199901)41:1<179::AID-MRM25>3.0.CO;2-V
See : Beatty et al., "Rapid Gridding Reconstruction with a Minimal Oversampling Ratio," IEEE TMI, 2005. https://doi.org/10.1109/TMI.2004.842452
Gnufft<float> G(dataLength, 2.0f, Nx, Ny, Nz, kx, ky, kz, ix, iy, iz);
Col<cx_float> kdata = G * image; // forward: gridding + FFT
Col<cx_float> recon = G / kdata; // adjoint: FFT + degridding
T1
: Floating-point precision type (float or double).
Variables¶
| Name | Description |
|---|---|
| kx | Number of image pixels (n1 = Nx * Ny * Nz). |
| ky | k-space y-coordinates (length n2, range [-Ny/2, Ny/2)). |
| kz | k-space z-coordinates (length n2, range [-Nz/2, Nz/2)). |
| ix | Image-space x-coordinates (length n1, stored for reference). |
| iy | Image-space y-coordinates (length n1, stored for reference). |
| iz | Image-space z-coordinates (length n1, stored for reference). |
| gridOS | Grid oversampling factor. |
| beta | Kaiser-Bessel kernel look-up table. |
| kernelWidth | Kaiser-Bessel kernel half-width in grid units. |
| stream | GPU stream handle (OpenACC/CUDA, NULL on CPU builds). |
| plan | cuFFT plan handle for GPU FFT on the oversampled grid. |
| plan | FFT plan handle (unused on CPU-only builds). |
| metalCtx | Metal gridding context (legacy); nullptr when T1 != float or Metal unavailable. |
| pipelineCtx | Full GPU NUFFT pipeline context (macOS 14+); nullptr if unavailable. |
| imageNumElems | Total number of elements in the (non-oversampled) image grid. |
| gridNumElems | Total number of elements in the oversampled grid. |
| pGridData | Real-valued grid buffers (image-size and oversampled) for host and device. |
| pSamples | Real-valued interleaved k-space sample buffer (length 2*n2). |
| gridData | Complex grid buffers (image-size and oversampled) for host and device. |
| samples | Complex k-space sample buffer (length n2). |
| XformedData | Scratch buffer for transformed k-space data (forward path). |
| XformedImg | Scratch buffer for transformed image data (adjoint path). |
| realXformedData | Real part of transformed k-space data (split-complex layout). |
| imagXformedData | Imaginary part of transformed k-space data (split-complex layout). |
| realXformedImg | Real part of transformed image data (split-complex layout). |
| imagXformedImg | Imaginary part of transformed image data (split-complex layout). |
Operators¶
| Name | Description |
|---|---|
| operator* | Forward NUFFT: image -> k-space via KB gridding. Applies deapodization, zero-pads to the oversampled grid, FFT-shifts, performs an FFT, and interpolates at the non-uniform k-space locations. d : Input image vector of length n1. Return : Output k-space vector of length n2. |
| operator/ | Adjoint NUFFT: k-space -> image via KB gridding. Spreads k-space samples onto the oversampled grid using the KB kernel, performs an inverse FFT, crops to image size, and applies deapodization. d : Input k-space vector of length n2. Return : Output image vector of length n1. |
| operator* | Forward NUFFT (forgeCol overload for Metal path). |
| operator/ | Adjoint NUFFT (forgeCol overload for Metal path). |
Functions¶
| Name | Description |
|---|---|
| Gnufft | Default constructor. |
| Gnufft | Construct a Gnufft operator with the given trajectory and image dimensions. |
| ~Gnufft | Destructor. |
| metalForwardImpl | Metal forward pipeline: deapodize → zero-pad → FFT → gridding. Writes result to pSamples (n2 complex elements). |
| metalAdjointImpl | Metal adjoint pipeline: gridding → IFFT → crop → deapodize. Writes result to pGridData (n1 complex elements). |
| forwardSpatialInterp | Forward spatial interpolation only (no deapodization or FFT). |
| adjointSpatialInterp | Adjoint spatial interpolation only (no deapodization or FFT). |
Variable Details¶
XformedData¶
mutable Col<CxT1> XformedData
Scratch buffer for transformed k-space data (forward path).
XformedImg¶
mutable Col<CxT1> XformedImg
Scratch buffer for transformed image data (adjoint path).
beta¶
T1 beta
Kaiser-Bessel kernel look-up table.
Number of entries in the KB kernel LUT.
KB kernel shape parameter (computed from gridOS and kernelWidth).
gridData¶
complex<T1>*gridData, *gridData_d, *gridData_os, *gridData_os_d
Complex grid buffers (image-size and oversampled) for host and device.
gridNumElems¶
uword gridNumElems
Total number of elements in the oversampled grid.
gridOS¶
T1 gridOS
Grid oversampling factor.
imagXformedData¶
mutable Col<T1> imagXformedData
Imaginary part of transformed k-space data (split-complex layout).
imagXformedImg¶
mutable Col<T1> imagXformedImg
Imaginary part of transformed image data (split-complex layout).
imageNumElems¶
uword imageNumElems
Total number of elements in the (non-oversampled) image grid.
ix¶
Col<T1> ix
Image-space x-coordinates (length n1, stored for reference).
iy¶
Col<T1> iy
Image-space y-coordinates (length n1, stored for reference).
iz¶
Col<T1> iz
Image-space z-coordinates (length n1, stored for reference).
kernelWidth¶
T1 kernelWidth
Kaiser-Bessel kernel half-width in grid units.
kx¶
T1* kx
Number of image pixels (n1 = Nx * Ny * Nz).
Number of k-space samples.
Image x-dimension in pixels.
Image y-dimension in pixels.
Image z-dimension in pixels.
k-space x-coordinates (length n2, range [-Nx/2, Nx/2)).
ky¶
T1* ky
k-space y-coordinates (length n2, range [-Ny/2, Ny/2)).
kz¶
T1* kz
k-space z-coordinates (length n2, range [-Nz/2, Nz/2)).
metalCtx¶
MetalGriddingContext* metalCtx
Metal gridding context (legacy); nullptr when T1 != float or Metal unavailable.
pGridData¶
T1 *pGridData, *pGridData_d, *pGridData_os, *pGridData_os_d
Real-valued grid buffers (image-size and oversampled) for host and device.
pSamples¶
T1* pSamples
Real-valued interleaved k-space sample buffer (length 2*n2).
pipelineCtx¶
MetalNufftPipelineContext* pipelineCtx
Full GPU NUFFT pipeline context (macOS 14+); nullptr if unavailable.
plan¶
cufftHandle plan
cuFFT plan handle for GPU FFT on the oversampled grid.
plan¶
void* plan
FFT plan handle (unused on CPU-only builds).
realXformedData¶
mutable Col<T1> realXformedData
Real part of transformed k-space data (split-complex layout).
realXformedImg¶
mutable Col<T1> realXformedImg
Real part of transformed image data (split-complex layout).
samples¶
complex<T1>* samples
Complex k-space sample buffer (length n2).
stream¶
void* stream
GPU stream handle (OpenACC/CUDA, NULL on CPU builds).
Operator Details¶
operator*¶
Col<CxT1> operator*(const Col<CxT1>& d) const
Forward NUFFT: image -> k-space via KB gridding.
Applies deapodization, zero-pads to the oversampled grid, FFT-shifts, performs an FFT, and interpolates at the non-uniform k-space locations.
d
: Input image vector of length n1.
Return
: Output k-space vector of length n2.
forgeCol<forgeComplex<T1>> operator*(const forgeCol<forgeComplex<T1>>& d) const
Forward NUFFT (forgeCol overload for Metal path).
d
: Input image vector of length n1.
Return
: Output k-space vector of length n2.
operator/¶
Col<CxT1> operator/(const Col<CxT1>& d) const
Adjoint NUFFT: k-space -> image via KB gridding.
Spreads k-space samples onto the oversampled grid using the KB kernel, performs an inverse FFT, crops to image size, and applies deapodization.
d
: Input k-space vector of length n2.
Return
: Output image vector of length n1.
forgeCol<forgeComplex<T1>> operator/(const forgeCol<forgeComplex<T1>>& d) const
Adjoint NUFFT (forgeCol overload for Metal path).
d
: Input k-space vector of length n2.
Return
: Output image vector of length n1.
Function Details¶
Gnufft¶
Gnufft()
Default constructor. Produces an uninitialized operator.
Gnufft(uword dataLength, T1 gridos, uword nx, uword ny, uword nz, const Col<T1>& k1, const Col<T1>& k2, const Col<T1>& k3, const Col<T1>& i1, const Col<T1>& i2, const Col<T1>& i3)
Construct a Gnufft operator with the given trajectory and image dimensions.
dataLength
: Number of k-space samples (n2, output of forward transform).
gridos
: Grid oversampling factor (typically 2.0).
nx
: Image x-dimension in pixels.
ny
: Image y-dimension in pixels.
nz
: Image z-dimension in pixels (use 1 for 2-D).
k1
: k-space x-coordinates, length dataLength (units: cycles, range [-nx/2, nx/2)).
k2
: k-space y-coordinates, length dataLength.
k3
: k-space z-coordinates, length dataLength.
i1
: Image-space x-coordinates, length nxnynz (not used in gridding, stored for reference).
i2
: Image-space y-coordinates, length nxnynz.
i3
: Image-space z-coordinates, length nxnynz.
adjointSpatialInterp¶
Col<CxT1> adjointSpatialInterp(const Col<CxT1>& d) const
Adjoint spatial interpolation only (no deapodization or FFT).
d
: Input k-space vector of length n2.
Return
: Output image vector of length n1.
forwardSpatialInterp¶
Col<CxT1> forwardSpatialInterp(const Col<CxT1>& d) const
Forward spatial interpolation only (no deapodization or FFT).
d
: Input image vector of length n1.
Return
: Spatially interpolated k-space vector of length n2.
metalAdjointImpl¶
void metalAdjointImpl(const T1* dataPtr) const
Metal adjoint pipeline: gridding → IFFT → crop → deapodize.
Writes result to pGridData (n1 complex elements).
metalForwardImpl¶
void metalForwardImpl(const T1* dataPtr) const
Metal forward pipeline: deapodize → zero-pad → FFT → gridding.
Writes result to pSamples (n2 complex elements).
~Gnufft¶
~Gnufft()
Destructor. Frees the KB kernel LUT and all internal grid buffers.