def test_checked_values():
    cs = CoordinateSystem('ijk', name='voxels', coord_dtype=np.float32)
    x = np.array([1, 2, 3], dtype=np.int16)
    xc = cs._checked_values(x)
    yield np.allclose, xc, x
    # wrong shape
    yield assert_raises, ValueError, cs._checked_values, x.reshape(3,1)
    # wrong length
    yield assert_raises, ValueError, cs._checked_values, x[0:2]
    # wrong dtype
    x = np.array([1,2,3], dtype=np.float64)
    yield assert_raises, ValueError, cs._checked_values, x
def resample_image(input_image,
                   new_size,
                   new_size_type,
                   interpolation='linear',
                   verbose=1):
    """This function will resample the specified input
    image to the target size.

    :param input_image: The input image.
    :param new_size: The target size, i.e. '0.25x0.25'
    :param new_size_type: Unit of resample (mm, vox, factor)
    :param interpolation: The interpolation type
    :param verbose: Verbosity level
    :return: The resampled image.
    """

    data = input_image.get_data()
    # Get dimensions of data
    p = input_image.header.get_zooms()
    n = input_image.header.get_data_shape()
    sct.printv('  pixdim: ' + str(p), verbose)
    sct.printv('  shape: ' + str(n), verbose)

    # Calculate new dimensions
    sct.printv('\nCalculate new dimensions...', verbose)
    # parse input argument
    new_size = new_size.split('x')
    # if 4d, add resampling factor to 4th dimension
    if len(p) == 4:
        new_size.append('1')
    # compute new shape based on specific resampling method
    if new_size_type == 'vox':
        n_r = tuple([int(new_size[i]) for i in range(len(n))])
    elif new_size_type == 'factor':
        if len(new_size) == 1:
            # isotropic resampling
            new_size = tuple([new_size[0] for i in range(len(n))])
        # compute new shape as: n_r = n * f
        n_r = tuple(
            [int(round(n[i] * float(new_size[i]))) for i in range(len(n))])
    elif new_size_type == 'mm':
        if len(new_size) == 1:
            # isotropic resampling
            new_size = tuple([new_size[0] for i in range(len(n))])
        # compute new shape as: n_r = n * (p_r / p)
        n_r = tuple([
            int(round(n[i] * float(p[i]) / float(new_size[i])))
            for i in range(len(n))
        ])
    else:
        sct.printv('\nERROR: new_size_type is not recognized.', 1, 'error')
    sct.printv('  new shape: ' + str(n_r), verbose)

    affine = input_image.coordmap.affine
    sct.printv('  affine matrix: \n' + str(affine))

    # create ref image
    arr_r = np.zeros(n_r)
    R = np.eye(len(n) + 1)
    for i in range(len(n)):
        R[i, i] = n[i] / float(n_r[i])
    affine_r = np.dot(affine, R)
    coordmap_r = input_image.coordmap
    coordmap_r.affine = affine_r
    nii_r = nipy.core.api.Image(arr_r, coordmap_r)

    sct.printv('\nCalculate affine transformation...', verbose)
    # create affine transformation
    transfo = R
    # if data are 4d, delete temporal dimension
    if len(p) == 4:
        transfo = np.delete(transfo, 3, 0)
        transfo = np.delete(transfo, 3, 1)
    # translate to account for voxel size (otherwise resulting image will be shifted by half a voxel). Modify the three first rows of the last column, corresponding to the translation.
    transfo[:3, -1] = np.array(
        ((R[0, 0] - 1) / 2, (R[1, 1] - 1) / 2, (R[2, 2] - 1) / 2), dtype='f8')
    sct.printv('  transfo: \n' + str(transfo), verbose)

    # set interpolation method
    if interpolation == 'nn':
        interp_order = 0
    elif interpolation == 'linear':
        interp_order = 1
    elif interpolation == 'spline':
        interp_order = 2

    # create 3d coordmap because resample only accepts 3d data (jcohenadad 2016-07-26)
    if len(n) == 4:
        coordmap3d = copy.deepcopy(input_image.coordmap)
        from nipy.core.reference.coordinate_system import CoordinateSystem
        coordmap3d.function_domain = CoordinateSystem('xyz')
        # create 3d affine transfo
        affine3d = np.delete(affine, 3, 0)
        affine3d = np.delete(affine3d, 3, 1)
        coordmap3d.affine = affine3d

    # resample data
    if len(n) == 3:
        data_r = n_resample(input_image,
                            transform=transfo,
                            reference=nii_r,
                            mov_voxel_coords=True,
                            ref_voxel_coords=True,
                            dtype='double',
                            interp_order=interp_order,
                            mode='nearest')
    elif len(n) == 4:
        data_r = np.zeros(n_r)

        # loop across 4th dimension
        for it in range(n[3]):
            # create 3d nipy-like data
            arr3d = data[:, :, :, it]
            nii3d = nipy.core.api.Image(arr3d, coordmap3d)
            arr_r3d = arr_r[:, :, :, it]
            nii_r3d = nipy.core.api.Image(arr_r3d, coordmap3d)
            # resample data
            data3d_r = n_resample(nii3d,
                                  transform=transfo,
                                  reference=nii_r3d,
                                  mov_voxel_coords=True,
                                  ref_voxel_coords=True,
                                  dtype='double',
                                  interp_order=interp_order,
                                  mode='nearest')
            data_r[:, :, :, it] = data3d_r.get_data()

    nii_r = nipy.core.api.Image(data_r, coordmap_r)

    return nii_r
def test_index():
    cs = CoordinateSystem('ijk')
    yield assert_equal, cs.index('i'), 0
    yield assert_equal, cs.index('j'), 1
    yield assert_equal, cs.index('k'), 2
    yield assert_raises, ValueError, cs.index, 'x'
def resample():
    """
    Resample data using nipy. Note: we cannot use msct_image because coordmap needs to be used.
    :return:
    """
    import nipy
    from nipy.algorithms.registration.resample import resample
    import numpy as np

    verbose = param.verbose

    # Load data
    sct.printv('\nLoad data...', verbose)
    nii = nipy.load_image(param.fname_data)
    data = nii.get_data()
    # Get dimensions of data
    p = nii.header.get_zooms()
    n = nii.header.get_data_shape()
    sct.printv('  pixdim: ' + str(p), verbose)
    sct.printv('  shape: ' + str(n), verbose)

    # Calculate new dimensions
    sct.printv('\nCalculate new dimensions...', verbose)
    # parse input argument
    new_size = param.new_size.split('x')
    # if 4d, add resampling factor to 4th dimension
    if len(p) == 4:
        new_size.append('1')
    # compute new shape based on specific resampling method
    if param.new_size_type == 'vox':
        n_r = tuple([int(new_size[i]) for i in range(len(n))])
    elif param.new_size_type == 'factor':
        if len(new_size) == 1:
            # isotropic resampling
            new_size = tuple([new_size[0] for i in range(len(n))])
        # compute new shape as: n_r = n * f
        n_r = tuple([int(round(n[i] * float(new_size[i]))) for i in range(len(n))])
    elif param.new_size_type == 'mm':
        if len(new_size) == 1:
            # isotropic resampling
            new_size = tuple([new_size[0] for i in range(len(n))])
        # compute new shape as: n_r = n * (p_r / p)
        n_r = tuple([int(round(n[i] * float(p[i]) / float(new_size[i]))) for i in range(len(n))])
    else:
        sct.printv('\nERROR: param.new_size_type is not recognized.', 1, 'error')
    sct.printv('  new shape: ' + str(n_r), verbose)

    # get_base_affine()
    affine = nii.coordmap.affine
    # if len(p) == 4:
    #     affine = np.delete(affine, 3, 0)
    #     affine = np.delete(affine, 3, 1)
    sct.printv('  affine matrix: \n' + str(affine))

    # create ref image
    arr_r = np.zeros(n_r)
    R = np.eye(len(n) + 1)
    for i in range(len(n)):
        R[i, i] = n[i] / float(n_r[i])
    affine_r = np.dot(affine, R)
    coordmap_r = nii.coordmap
    coordmap_r.affine = affine_r
    nii_r = nipy.core.api.Image(arr_r, coordmap_r)

    sct.printv('\nCalculate affine transformation...', verbose)
    # create affine transformation
    transfo = R
    # if data are 4d, delete temporal dimension
    if len(p) == 4:
        transfo = np.delete(transfo, 3, 0)
        transfo = np.delete(transfo, 3, 1)
    # translate to account for voxel size (otherwise resulting image will be shifted by half a voxel). Modify the three first rows of the last column, corresponding to the translation.
    transfo[:3, -1] = np.array(((R[0, 0] - 1) / 2, (R[1, 1] - 1) / 2, (R[2, 2] - 1) / 2), dtype='f8')
    # sct.printv(transfo)
    sct.printv('  transfo: \n' + str(transfo), verbose)

    # set interpolation method
    if param.interpolation == 'nn':
        interp_order = 0
    elif param.interpolation == 'linear':
        interp_order = 1
    elif param.interpolation == 'spline':
        interp_order = 2

    # create 3d coordmap because resample only accepts 3d data (jcohenadad 2016-07-26)
    if len(n) == 4:
        from copy import deepcopy
        coordmap3d = deepcopy(nii.coordmap)
        from nipy.core.reference.coordinate_system import CoordinateSystem
        coordmap3d.__setattr__('function_domain', CoordinateSystem('xyz'))
        # create 3d affine transfo
        affine3d = np.delete(affine, 3, 0)
        affine3d = np.delete(affine3d, 3, 1)
        coordmap3d.affine = affine3d

    # resample data
    if len(n) == 3:
        data_r = resample(nii, transform=transfo, reference=nii_r, mov_voxel_coords=True, ref_voxel_coords=True, dtype='double', interp_order=interp_order, mode='nearest')
    elif len(n) == 4:
        data_r = np.zeros(n_r)
        # data_r = np.zeros(n_r[0:3])
        # data_r = np.expand_dims(data_r, 3)
        # loop across 4th dimension
        for it in range(n[3]):
            # create 3d nipy-like data
            arr3d = data[:, :, :, it]
            nii3d = nipy.core.api.Image(arr3d, coordmap3d)
            arr_r3d = arr_r[:, :, :, it]
            nii_r3d = nipy.core.api.Image(arr_r3d, coordmap3d)
            # resample data
            data3d_r = resample(nii3d, transform=transfo, reference=nii_r3d, mov_voxel_coords=True, ref_voxel_coords=True, dtype='double', interp_order=interp_order, mode='nearest')
            # data_r = np.concatenate((data_r, data3d_r), axis=3)
            data_r[:, :, :, it] = data3d_r.get_data()

    # build output file name
    if param.fname_out == '':
        fname_out = sct.add_suffix(param.fname_data, '_r')
    else:
        fname_out = param.fname_out

    # save data
    nii_r = nipy.core.api.Image(data_r, coordmap_r)
    nipy.save_image(nii_r, fname_out)

    # to view results
    sct.printv('\nDone! To view results, type:', verbose)
    sct.printv('fslview ' + fname_out + ' &', verbose, 'info')

    # new_im = Image(param=new_data)
    # new_im.absolutepath = param.fname_out
    # new_im.path = path_out
    # new_im.file_name = file_out
    # new_im.ext = ext_out

    # zooms_to_set = list(new_zooms)
    # if dim == 4:
    #     zooms_to_set.append(nt)

    # new_im.hdr = input_im.hdr
    # new_im.hdr.set_zooms(zooms_to_set)

    # Set the new sform and qform:
    # new_im.hdr.set_sform(new_affine)
    # new_im.hdr.set_qform(new_affine)
    #
    # new_im.save()

    # extract resampling factor
    # sct.printv('\nParse resampling factor...', param.verbose)
    # new_size_split = param.new_size.split('x')
    # new_size = [float(new_size_split[i]) for i in range(len(new_size_split))]
    # # check if it has three values
    # if not len(new_size) == 3:
    #     sct.printv('\nERROR: new size should have three dimensions. E.g., 2x2x1.\n', 1, 'error')
    # else:
    #     ns_x, ns_y, ns_z = new_size
    #
    # # Extract path/file/extension
    # path_data, file_data, ext_data = sct.extract_fname(param.fname_data)
    # path_out, file_out, ext_out = '', file_data, ext_data
    # else:
    #     file_out += param.file_suffix
    # param.fname_out = path_out+file_out+ext_out
    #
    # input_im = Image(param.fname_data)

    # import numpy as np
    # affine_new = np.array([[2., 0., 0., 1],
    #                 [0., 2., 0., 1],
    #                 [0., 0., 2., 0],
    #                 [0., 0., 0., 1.]])
    # import nibabel
    # img = nibabel.Nifti1Image(input_im.data, affine=affine_new)
    # from nilearn.image import resample_img
    # new_data = resample_img(img, target_affine=np.eye(4), target_shape=(60, 60, 27))
    # sct.printv(new_data.shape)

    # display
    # from matplotlib.pylab import *
    # matshow(data[:, :, 15], cmap=cm.gray), show()
    # matshow(data_r[:, :, 15], cmap=cm.gray), show()

    # # translate before interpolation to account for voxel size
    # from skimage import transform
    # transform.resize()
    #
    #
    # zooms = (px, py, pz)  # input_im.hdr.get_zooms()[:3]
    # affine = input_im.hdr.get_qform()  # get_base_affine()
    # new_zooms = (px_new, py_new, pz_new)
    #
    # if type(param.interpolation) == int:
    #     order = param.interpolation
    # elif type(param.interpolation) == str and param.interpolation in param.x_to_order.keys():
    #     order = param.x_to_order[param.interpolation]
    # else:
    #     order = 1
    #     sct.printv('WARNING: wrong input for the interpolation. Using default value = linear', param.verbose, 'warning')

    import numpy as np