示例#1
0
 def _apply(self, input):
     device = backend.get_device(input)
     with device:
         coord = backend.to_device(self.coord, device)
         return interp.gridding(input, coord, self.oshape,
                                kernel=self.kernel,
                                width=self.width, param=self.param)
示例#2
0
    def _apply(self, input):
        device = backend.get_device(input)
        coord = backend.to_device(self.coord, device)
        kernel = backend.to_device(self.kernel, device)

        with device:
            return interp.gridding(input, self.oshape, self.width, kernel,
                                   coord)
示例#3
0
def nufft_adjoint(input, coord, oshape=None, oversamp=1.25, width=4):
    """Adjoint non-uniform Fast Fourier Transform.

    Args:
        input (array): input Fourier domain array of shape
            (...) + coord.shape[:-1]. That is, the last dimensions
            of input must match the first dimensions of coord.
            The nufft_adjoint is applied on the last coord.ndim - 1 axes,
            and looped over the remaining axes.
        coord (array): Fourier domain coordinate array of shape (..., ndim).
            ndim determines the number of dimension to apply nufft adjoint.
            coord[..., i] should be scaled to have its range between
            -n_i // 2, and n_i // 2.
        oshape (tuple of ints): output shape of the form
            (..., n_{ndim - 1}, ..., n_1, n_0).
        oversamp (float): oversampling factor.
        width (float): interpolation kernel full-width in terms of
            oversampled grid.
        n (int): number of sampling points of the interpolation kernel.

    Returns:
        array: signal domain array with shape specified by oshape.

    See Also:
        :func:`sigpy.nufft.nufft`

    """
    ndim = coord.shape[-1]
    beta = np.pi * (((width / oversamp) * (oversamp - 0.5))**2 - 0.8)**0.5
    if oshape is None:
        oshape = list(input.shape[:-coord.ndim + 1]) + estimate_shape(coord)
    else:
        oshape = list(oshape)

    os_shape = _get_oversamp_shape(oshape, ndim, oversamp)

    # Gridding
    coord = _scale_coord(coord, oshape, oversamp)
    output = interp.gridding(input,
                             coord,
                             os_shape,
                             kernel='kaiser_bessel',
                             width=width,
                             param=beta)
    output /= width**ndim

    # IFFT
    output = ifft(output, axes=range(-ndim, 0), norm=None)

    # Crop
    output = util.resize(output, oshape)
    output *= util.prod(os_shape[-ndim:]) / util.prod(oshape[-ndim:])**0.5

    # Apodize
    _apodize(output, ndim, oversamp, width, beta)

    return output
示例#4
0
        def test_gridding_cpu_gpu(self):
            for ndim in [1, 2, 3]:
                for dtype in [np.float32, np.complex64]:
                    with self.subTest(ndim=ndim, dtype=dtype):
                        shape = [2, 20] + [1] * (ndim - 1)
                        coord = np.random.random([10, ndim])

                        input = np.random.random([2, 10] + [1] *
                                                 (ndim - 1)).astype(
                                                     dtype=dtype)
                        output_cpu = interp.gridding(input,
                                                     coord,
                                                     shape,
                                                     kernel="kaiser_bessel")
                        output_gpu = interp.gridding(
                            cp.array(input),
                            cp.array(coord),
                            shape,
                            kernel="kaiser_bessel").get()
                        np.testing.assert_allclose(output_cpu,
                                                   output_gpu,
                                                   atol=1e-5)
示例#5
0
    def test_gridding(self):

        batch = 2

        for ndim in [1, 2, 3]:
            shape = [3] + [1] * (ndim - 1)
            width = 2.0
            kernel = np.array([1.0, 0.5])
            coord = np.array([[0.1] + [0] * (ndim - 1),
                              [1.1] + [0] * (ndim - 1),
                              [2.1] + [0] * (ndim - 1)])

            input = np.array([[0, 1.0, 0]] * batch)
            output = interp.gridding(input, [batch] + shape, width, kernel,
                                     coord)
            output_expected = np.array([[0, 0.9, 0.1]] *
                                       batch).reshape([batch] + shape)
            np.testing.assert_allclose(output, output_expected)
示例#6
0
        def test_gridding_cuda(self):

            batch = 2
            for ndim in [1, 2, 3]:
                for dtype in [np.float, np.complex64, np.complex]:
                    shape = [3] + [1] * (ndim - 1)
                    width = 2.0
                    kernel = cp.array([1.0, 0.5])
                    coord = cp.array([[0.1] + [0] * (ndim - 1),
                                      [1.1] + [0] * (ndim - 1),
                                      [2.1] + [0] * (ndim - 1)])

                    input = cp.array([[0, 1.0, 0]] * batch, dtype=dtype)
                    output = interp.gridding(input, [batch] + shape, width,
                                             kernel, coord)
                    output_expected = cp.array([[0, 0.9, 0.1]] * batch,
                                               dtype=dtype).reshape([batch] +
                                                                    shape)
                    cp.testing.assert_allclose(output,
                                               output_expected,
                                               atol=1e-7)
示例#7
0
    def test_gridding_spline(self):
        xps = [np]
        if config.cupy_enabled:
            xps.append(cp)

        batch = 2
        for xp in xps:
            for ndim in [1, 2, 3]:
                for dtype in [np.float32, np.complex64]:
                    with self.subTest(ndim=ndim, xp=xp, dtype=dtype):
                        shape = [3] + [1] * (ndim - 1)
                        coord = xp.array([[0.1] + [0] * (ndim - 1),
                                          [1.1] + [0] * (ndim - 1),
                                          [2.1] + [0] * (ndim - 1)])

                        input = xp.array([[0, 1.0, 0]] * batch, dtype=dtype)
                        output = interp.gridding(input, coord, [batch] + shape)
                        output_expected = xp.array(
                            [[0, 0.9, 0.1]] * batch).reshape([batch] + shape)
                        xp.testing.assert_allclose(output,
                                                   output_expected,
                                                   atol=1e-7)
示例#8
0
    def test_gridding(self):
        xps = [np]
        if config.cupy_enabled:
            xps.append(cp)

        batch = 2
        for xp in xps:
            for ndim in [1, 2, 3]:
                with self.subTest(ndim=ndim, xp=xp):
                    shape = [3] + [1] * (ndim - 1)
                    width = 2.0
                    kernel = xp.array([1.0, 0.5])
                    coord = xp.array([[0.1] + [0] * (ndim - 1),
                                      [1.1] + [0] * (ndim - 1),
                                      [2.1] + [0] * (ndim - 1)])

                    input = xp.array([[0, 1.0, 0]] * batch)
                    output = interp.gridding(input, [batch] + shape, width,
                                             kernel, coord)
                    output_expected = xp.array([[0, 0.9, 0.1]] *
                                               batch).reshape([batch] + shape)
                    xp.testing.assert_allclose(output,
                                               output_expected,
                                               atol=1e-7)
示例#9
0
def nufftiii_adjoint(input, shape, icoord, ocoord, oversamp=1.25, width=4):
    """Type III Non-uniform Fast Fourier Transform.

    Args:
        input (array): input signal domain array of shape
            (..., n_{ndim - 1}, ..., n_1, n_0),
            where ndim is specified by coord.shape[-1]. The nufft
            is applied on the last ndim axes, and looped over
            the remaining axes.
        coord (array): Fourier domain coordinate array of shape (..., ndim).
            ndim determines the number of dimensions to apply the nufft.
            coord[..., i] should be scaled to have its range between
            -n_i // 2, and n_i // 2.
        oversamp (float): oversampling factor.
        width (float): interpolation kernel full-width in terms of
            oversampled grid.
        n (int): number of sampling points of the interpolation kernel.

    Returns:
        array: Fourier domain data of shape
            input.shape[:-ndim] + coord.shape[:-1].

    References:
        Fessler, J. A., & Sutton, B. P. (2003).
        Nonuniform fast Fourier transforms using min-max interpolation
        IEEE Transactions on Signal Processing, 51(2), 560-574.
        Beatty, P. J., Nishimura, D. G., & Pauly, J. M. (2005).
        Rapid gridding reconstruction with a minimal oversampling ratio.
        IEEE transactions on medical imaging, 24(6), 799-808.

    """
    ndim = icoord.shape[-1]
    beta = np.pi * (((width / oversamp) * (oversamp - 0.5))**2 - 0.8)**0.5
    #shape = estimate_shape(-icoord)
    
    # adjoint NUFFT
    os_shape = _get_oversamp_shape(list(shape), ndim, oversamp)

    # Gridding
    coord = _scale_coord(ocoord, shape, oversamp)
    output = interp.gridding(input, coord, os_shape,
                             kernel='kaiser_bessel', width=width, param=beta)
    output /= width**ndim

    # Forward NUFFT
    # Apodize
    #_apodize(output, ndim, oversamp, width, beta)

    # IFFT
    output = ifft(output, axes=range(-ndim, 0), norm=None)

    # Crop
    output = util.resize(output, shape)
    output *= util.prod(os_shape[-ndim:]) / util.prod(shape[-ndim:])**0.5

    # Apodize
    _apodize(output, ndim, oversamp, width, beta)

    

    # Inverse FFT
    output = fft(output, axes=range(-ndim, 0), center=True)
    
    

    # Forward NUFFT
    # Apodize
    _apodize(output, ndim, oversamp, width, beta)

    # Zero-pad
    output /= util.prod(output.shape[-ndim:])**0.5
    output = util.resize(output, os_shape)

    # FFT
    output = fft(output, axes=range(-ndim, 0), norm=None)

    # Interpolate
    coord = _scale_coord(-icoord, shape, oversamp)
    output = interp.interpolate(
        output, coord, kernel='kaiser_bessel', width=width, param=beta)
    output /= width**ndim


    return output