np.save('datas/' + title + '.npy', save_pynufft)

# Plot K-space
# kx = np.real(y_pynufft)
# ky = np.imag(y_pynufft)
# plt.figure()
# plt.plot(kx,ky, 'w.')
# ax = plt.gca()
# ax.set_facecolor('k')
# plt.title('K-space Pynufft')
# plt.show()
if adj == True:
    # backward test
    print('Self-adjoint Test...')
    if gpu == True:
        gx2 = NufftObj.adjoint(gy)
        img_reconstruct_ = gx2.get()

    else:
        img_reconstruct_ = NufftObj.adjoint(y_pynufft)

    # print(np.abs(img_reconstruct_)/np.max(np.abs(img_reconstruct_)))

    img_reconstruct = np.abs(img_reconstruct_) / np.max(
        np.abs(img_reconstruct_))
    img_reconstruct = img_reconstruct.astype(np.float64)
    # plt.figure()
    # plt.suptitle('Comparaison original/selfadjoint')
    # plt.subplot(121)
    # plt.imshow(image, cmap='gray')
    # plt.subplot(122)
Beispiel #2
0
# nufftObj.x_Nd = nufftObj.thr.to_device(Il[:3].astype(dtype))
# gx = nufftObj.thr.copy_array(nufftObj.x_Nd)

#x = numpy.einsum('cxyz -> xyzc', Il[0:3]).copy() # coil must be the last dimension; Assume it is a C-order array



gy = nufftObj.forward(x)
#y = np.copy(gy.get())

# Checking the shape of the kspace
#print("K-space shapes: ", y.shape)

# Computing the backward pass

gx2 = nufftObj.adjoint(gy)
rec_Il = gx2.get() #np.copy(gx.get())
print(rec_Il.shape)
# Plotting the results
import matplotlib.pyplot
matplotlib.pyplot.subplot(2,3,1)
matplotlib.pyplot.imshow(x[:,:,64,0].real)
matplotlib.pyplot.title('input_image (64-th slice, first coil)')
matplotlib.pyplot.subplot(2,3,2)
matplotlib.pyplot.imshow(x[:,:,64,1].real)
matplotlib.pyplot.title('input_image (64-th slice, second coil)')
matplotlib.pyplot.subplot(2,3,3)
matplotlib.pyplot.imshow(x[:,:,64,2].real)
matplotlib.pyplot.title('input_image (64-th slice, third coil)')

Beispiel #3
0
class NUFFT(Singleton):
    """  GPU implementation of N-D non uniform Fast Fourrier Transform class.

    Attributes
    ----------
    samples: np.ndarray
        the mask samples in the Fourier domain.
    shape: tuple of int
        shape of the image (necessarly a square/cubic matrix).
    nufftObj: The pynufft object
        depending on the required computational platform
    platform: string, 'opencl' or 'cuda'
        string indicating which hardware platform will be used to compute the
        NUFFT
    Kd: int or tuple
        int or tuple indicating the size of the frequency grid, for regridding.
        if int, will be evaluated to (Kd,)*nb_dim of the image
    Jd: int or tuple
        Size of the interpolator kernel. If int, will be evaluated
        to (Jd,)*dims image
    n_coils: int default 1
            Number of coils used to acquire the signal in case of multiarray
            receiver coils acquisition. If n_coils > 1, please organize data as
            n_coils X data_per_coil
    """
    numOfInstances = 0

    def __init__(self,
                 samples,
                 shape,
                 platform='cuda',
                 Kd=None,
                 Jd=None,
                 n_coils=1,
                 verbosity=0):
        """ Initilize the 'NUFFT' class.

        Parameters
        ----------
        samples: np.ndarray
            the mask samples in the Fourier domain.
        shape: tuple of int
            shape of the image (necessarly a square/cubic matrix).
        platform: string, 'cpu', 'opencl' or 'cuda'
            string indicating which hardware platform will be used to
            compute the NUFFT
        Kd: int or tuple
            int or tuple indicating the size of the frequency grid,
            for regridding. If int, will be evaluated
            to (Kd,)*nb_dim of the image
        Jd: int or tuple
            Size of the interpolator kernel. If int, will be evaluated
            to (Jd,)*dims image
        n_coils: int
            Number of coils used to acquire the signal in case of multiarray
            receiver coils acquisition
        """
        if (n_coils < 1) or (type(n_coils) is not int):
            raise ValueError('The number of coils should be an integer >= 1')
        if not pynufft_available:
            raise ValueError('PyNUFFT Package is not installed, please '
                             'consider using `gpuNUFFT` or install the '
                             'PyNUFFT package')
        self.nb_coils = n_coils
        self.shape = shape
        self.platform = platform
        self.samples = samples * (2 * np.pi)  # Pynufft use samples in
        # [-pi, pi[ instead of [-0.5, 0.5[
        self.dim = samples.shape[1]  # number of dimensions of the image

        if type(Kd) == int:
            self.Kd = (Kd, ) * self.dim
        elif type(Kd) == tuple:
            self.Kd = Kd
        elif Kd is None:
            # Preferential option
            self.Kd = tuple([2 * ix for ix in shape])

        if type(Jd) == int:
            self.Jd = (Jd, ) * self.dim
        elif type(Jd) == tuple:
            self.Jd = Jd
        elif Jd is None:
            # Preferential option
            self.Jd = (5, ) * self.dim

        for (i, s) in enumerate(shape):
            assert (self.shape[i] <= self.Kd[i]), 'size of frequency grid' + \
                                                  'must be greater or equal ' \
                                                  'than the image size'
        if verbosity > 0:
            print('Creating the NUFFT object...')
        if self.platform == 'opencl':
            warn('Attemping to use OpenCL plateform. Make sure to '
                 'have  all the dependecies installed')
            Singleton.__init__(self)
            if self.getNumInstances() > 1:
                warn('You have created more than one NUFFT object. '
                     'This could cause memory leaks')
            self.nufftObj = NUFFT_hsa(API='ocl',
                                      platform_number=None,
                                      device_number=None,
                                      verbosity=verbosity)

            self.nufftObj.plan(
                om=self.samples,
                Nd=self.shape,
                Kd=self.Kd,
                Jd=self.Jd,
                batch=1,  # TODO self.nb_coils,
                ft_axes=tuple(range(samples.shape[1])),
                radix=None)

        elif self.platform == 'cuda':
            warn('Attemping to use Cuda plateform. Make sure to '
                 'have  all the dependecies installed and '
                 'to create only one instance of NUFFT GPU')
            Singleton.__init__(self)
            if self.getNumInstances() > 1:
                warn('You have created more than one NUFFT object. '
                     'This could cause memory leaks')
            self.nufftObj = NUFFT_hsa(API='cuda',
                                      platform_number=None,
                                      device_number=None,
                                      verbosity=verbosity)

            self.nufftObj.plan(
                om=self.samples,
                Nd=self.shape,
                Kd=self.Kd,
                Jd=self.Jd,
                batch=1,  # TODO self.nb_coils,
                ft_axes=tuple(range(samples.shape[1])),
                radix=None)

        else:
            raise ValueError('Wrong type of platform. Platform must be'
                             '\'opencl\' or \'cuda\'')

    def __del__(self):
        # This is an important desctructor to ensure that the device memory
        # is freed
        # TODO this is still not freeing the memory right on device.
        # Mostly issue with reikna library.
        # Refer : https://github.com/fjarri/reikna/issues/53
        if self.platform == 'opencl' or self.platform == 'cuda':
            self.nufftObj.release()

    def op(self, img):
        """ This method calculates the masked non-cartesian Fourier transform
        of a 3-D image.

        Parameters
        ----------
        img: np.ndarray
            input 3D array with the same shape as shape.

        Returns
        -------
        x: np.ndarray
            masked Fourier transform of the input image.
        """
        if self.nb_coils == 1:
            dtype = np.complex64
            # Send data to the mCPU/GPU platform
            self.nufftObj.x_Nd = self.nufftObj.thr.to_device(img.astype(dtype))
            gx = self.nufftObj.thr.copy_array(self.nufftObj.x_Nd)
            # Forward operator of the NUFFT
            gy = self.nufftObj.forward(gx)
            y = np.squeeze(gy.get())
        else:
            dtype = np.complex64
            # Send data to the mCPU/GPU platform
            y = []
            for ch in range(self.nb_coils):
                self.nufftObj.x_Nd = self.nufftObj.thr.to_device(
                    np.copy(img[ch]).astype(dtype))
                gx = self.nufftObj.thr.copy_array(self.nufftObj.x_Nd)
                # Forward operator of the NUFFT
                gy = self.nufftObj.forward(gx)
                y.append(np.squeeze(gy.get()))
            y = np.asarray(y)
        return y * 1.0 / np.sqrt(np.prod(self.Kd))

    def adj_op(self, x):
        """ This method calculates inverse masked non-uniform Fourier
        transform of a 1-D coefficients array.

        Parameters
        ----------
        x: np.ndarray
            masked non-uniform Fourier transform 1D data.

        Returns
        -------
        img: np.ndarray
            inverse 3D discrete Fourier transform of the input coefficients.
        """
        if self.nb_coils == 1:
            dtype = np.complex64
            cuda_array = self.nufftObj.thr.to_device(x.astype(dtype))
            gx = self.nufftObj.adjoint(cuda_array)
            img = np.squeeze(gx.get())
        else:
            dtype = np.complex64
            img = []
            for ch in range(self.nb_coils):
                cuda_array = self.nufftObj.thr.to_device(
                    np.copy(x[ch]).astype(dtype))
                gx = self.nufftObj.adjoint(cuda_array)
                img.append(gx.get())
            img = np.asarray(np.squeeze(img))
        return img * np.sqrt(np.prod(self.Kd))