Source code for mrinufft.operators.interfaces.nfft
"""An implementation of the NUDFT using numpy."""
import numpy as np
from ..base import FourierOperatorCPU
PYNFFT_AVAILABLE = True
try:
import pynfft
except ImportError:
PYNUFFT_AVAILABLE = False
[docs]
def get_fourier_matrix(ktraj, shape, ndim, do_ifft=False):
"""Get the NDFT Fourier Matrix."""
n = np.prod(shape)
matrix = np.zeros((n, n), dtype=complex)
r = [np.arange(shape[i]) for i in range(ndim)]
grid_r = np.reshape(np.meshgrid(*r, indexing="ij"), (ndim, np.prod(shape)))
traj_grid = ktraj @ grid_r
matrix = np.exp(-2j * np.pi * traj_grid)
if do_ifft:
matrix = matrix.conj().T
return matrix / np.sqrt(n)
[docs]
class RawPyNFFT:
"""Implementation of the NUDFT using numpy."""
def __init__(self, samples, shape):
self.samples = samples
self.shape = shape
self.ndim = len(shape)
self.plan = pynfft.NFFT(N=shape, M=len(samples))
self.plan.x = self.samples
self.plan.precompute()
self.shape = shape
[docs]
def op(self, coeffs, image):
"""Compute the forward NUDFT."""
self.plan.f_hat = image
np.copyto(coeffs, self.plan.trafo())
return coeffs
[docs]
def adj_op(self, coeffs, image):
"""Compute the adjoint NUDFT."""
self.plan.f = coeffs
np.copyto(image, self.plan.adjoint())
return image
[docs]
class MRInfft(FourierOperatorCPU):
"""MRI operator using numpy NUDFT backend.
For testing purposes only, as it is very slow.
"""
backend = "pynfft"
available = PYNFFT_AVAILABLE
def __init__(
self, samples, shape, n_coils=1, n_batchs=1, smaps=None, density=False
):
super().__init__(
samples,
shape,
n_coils=n_coils,
n_batchs=n_batchs,
n_trans=1,
smaps=smaps,
density=density,
raw_op=None, # is set later, after normalizing samples.
)
self.raw_op = RawPyNFFT(self.samples, shape)