Exemplo n.º 1
0
    def execute(self):
        """
        This method executes the symmetry detection
        :return: returns the symmetry data
        """
        img = Image(self.input_image)
        raw_orientation = img.change_orientation()
        data = np.squeeze(img.data)
        dim = data.shape
        section_length = dim[1]/self.nb_sections

        result = np.zeros(dim)

        for i in range(0, self.nb_sections):
            if (i+1)*section_length > dim[1]:
                y_length = (i+1)*section_length - ((i+1)*section_length - dim[1])
                result[:, i*section_length:i*section_length + y_length, :] = symmetry_detector_right_left(data[:, i*section_length:i*section_length + y_length, :],  cropped_xy=self.crop_xy)
            sym = symmetry_detector_right_left(data[:, i*section_length:(i+1)*section_length, :], cropped_xy=self.crop_xy)
            result[:, i*section_length:(i+1)*section_length, :] = sym

        result_image = Image(img)
        if len(result_image.data) == 4:
            result_image.data = result[:,:,:,np.newaxis]
        else:
            result_image.data = result

        result_image.change_orientation(raw_orientation)

        return result_image.data
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix):
    """
    Compute DTI.
    :param fname_in: input 4d file.
    :param bvals: bvals txt file
    :param bvecs: bvecs txt file
    :param prefix: output prefix. Example: "dti_"
    :return: True/False
    """
    # Open file.
    from msct_image import Image
    nii = Image(fname_in)
    data = nii.data
    print('data.shape (%d, %d, %d, %d)' % data.shape)

    # open bvecs/bvals
    from dipy.io import read_bvals_bvecs
    bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs)
    from dipy.core.gradients import gradient_table
    gtab = gradient_table(bvals, bvecs)

    # # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image.
    # from dipy.segment.mask import median_otsu
    # maskdata, mask = median_otsu(data, 3, 1, True, vol_idx=range(10, 50), dilate=2)
    # print('maskdata.shape (%d, %d, %d, %d)' % maskdata.shape)

    # fit tensor model
    import dipy.reconst.dti as dti
    tenmodel = dti.TensorModel(gtab)
    tenfit = tenmodel.fit(data)

    # Compute metrics
    printv('Computing metrics...', param.verbose)
    # FA
    from dipy.reconst.dti import fractional_anisotropy
    nii.data = fractional_anisotropy(tenfit.evals)
    nii.setFileName(prefix + 'FA.nii.gz')
    nii.save('float32')
    # MD
    from dipy.reconst.dti import mean_diffusivity
    nii.data = mean_diffusivity(tenfit.evals)
    nii.setFileName(prefix + 'MD.nii.gz')
    nii.save('float32')
    # RD
    from dipy.reconst.dti import radial_diffusivity
    nii.data = radial_diffusivity(tenfit.evals)
    nii.setFileName(prefix + 'RD.nii.gz')
    nii.save('float32')
    # AD
    from dipy.reconst.dti import axial_diffusivity
    nii.data = axial_diffusivity(tenfit.evals)
    nii.setFileName(prefix + 'AD.nii.gz')
    nii.save('float32')

    return True
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix):
    """
    Compute DTI.
    :param fname_in: input 4d file.
    :param bvals: bvals txt file
    :param bvecs: bvecs txt file
    :param prefix: output prefix. Example: "dti_"
    :return: True/False
    """
    # Open file.
    from msct_image import Image
    nii = Image(fname_in)
    data = nii.data
    print('data.shape (%d, %d, %d, %d)' % data.shape)

    # open bvecs/bvals
    from dipy.io import read_bvals_bvecs
    bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs)
    from dipy.core.gradients import gradient_table
    gtab = gradient_table(bvals, bvecs)

    # # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image.
    # from dipy.segment.mask import median_otsu
    # maskdata, mask = median_otsu(data, 3, 1, True, vol_idx=range(10, 50), dilate=2)
    # print('maskdata.shape (%d, %d, %d, %d)' % maskdata.shape)

    # fit tensor model
    import dipy.reconst.dti as dti
    tenmodel = dti.TensorModel(gtab)
    tenfit = tenmodel.fit(data)

    # Compute metrics
    printv('Computing metrics...', param.verbose)
    # FA
    from dipy.reconst.dti import fractional_anisotropy
    nii.data = fractional_anisotropy(tenfit.evals)
    nii.setFileName(prefix+'FA.nii.gz')
    nii.save('float32')
    # MD
    from dipy.reconst.dti import mean_diffusivity
    nii.data = mean_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'MD.nii.gz')
    nii.save('float32')
    # RD
    from dipy.reconst.dti import radial_diffusivity
    nii.data = radial_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'RD.nii.gz')
    nii.save('float32')
    # AD
    from dipy.reconst.dti import axial_diffusivity
    nii.data = axial_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'AD.nii.gz')
    nii.save('float32')

    return True
Exemplo n.º 4
0
def main(args=None):

    dim_list = ['x', 'y', 'z', 't']

    if not args:
        args = sys.argv[1:]

    # Get parser info
    parser = get_parser()
    arguments = parser.parse(sys.argv[1:])
    fname_in = arguments["-i"]
    fname_out = arguments["-o"]
    verbose = int(arguments['-v'])

    # Build fname_out
    if fname_out == '':
        path_in, file_in, ext_in = extract_fname(fname_in)
        fname_out = path_in + file_in + '_mean' + ext_in

    # Open file.
    nii = Image(fname_in)
    data = nii.data

    # run command
    if '-otsu' in arguments:
        param = arguments['-otsu']
        data_out = otsu(data, param)
    elif '-otsu_adap' in arguments:
        param = arguments['-otsu_adap']
        data_out = otsu_adap(data, param[0], param[1])
    elif '-otsu_median' in arguments:
        param = arguments['-otsu_median']
        data_out = otsu_median(data, param[0], param[1])
    elif '-thr' in arguments:
        param = arguments['-thr']
        data_out = threshold(data, param)
    elif '-percent' in arguments:
        param = arguments['-percent']
        data_out = perc(data, param)
    elif '-mean' in arguments:
        dim = dim_list.index(arguments['-mean'])
        data_out = compute_mean(data, dim)
    elif '-std' in arguments:
        dim = dim_list.index(arguments['-std'])
        data_out = compute_std(data, dim)
    elif '-dilate' in arguments:
        data_out = dilate(data, arguments['-dilate'])
    elif '-erode' in arguments:
        data_out = erode(data, arguments['-dilate'])
    else:
        printv('No process applied.', 1, 'warning')
        return

    # Write output
    nii.data = data_out
    nii.setFileName(fname_out)
    nii.save()

    # display message
    printv('Created file:\n--> ' + fname_out + '\n', verbose, 'info')
Exemplo n.º 5
0
    def crop_from_mask_with_background(self):
        from numpy import asarray, einsum
        image_in = Image(self.input_filename)
        data_array = asarray(image_in.data)
        data_mask = asarray(Image(self.mask).data)
        assert data_array.shape == data_mask.shape

        # Element-wise matrix multiplication:
        new_data = None
        dim = len(data_array.shape)
        if dim == 3:
            new_data = einsum('ijk,ijk->ijk', data_mask, data_array)
        elif dim == 2:
            new_data = einsum('ij,ij->ij', data_mask, data_array)

        if self.background != 0:
            from sct_maths import get_data_or_scalar
            data_background = get_data_or_scalar(str(self.background), data_array)
            data_mask_inv = data_mask.max() - data_mask
            if dim == 3:
                data_background = einsum('ijk,ijk->ijk', data_mask_inv, data_background)
            elif dim == 2:
                data_background = einsum('ij,ij->ij', data_mask_inv, data_background)
            new_data += data_background

        # set image out
        image_in.setFileName(self.output_filename)
        image_in.data = new_data
        image_in.save()
Exemplo n.º 6
0
    def crop_from_mask_with_background(self):
        from numpy import asarray, einsum
        image_in = Image(self.input_filename)
        data_array = asarray(image_in.data)
        data_mask = asarray(Image(self.mask).data)
        assert data_array.shape == data_mask.shape

        # Element-wise matrix multiplication:
        new_data = None
        dim = len(data_array.shape)
        if dim == 3:
            new_data = einsum('ijk,ijk->ijk', data_mask, data_array)
        elif dim == 2:
            new_data = einsum('ij,ij->ij', data_mask, data_array)

        if self.background != 0:
            from sct_maths import get_data_or_scalar
            data_background = get_data_or_scalar(str(self.background),
                                                 data_array)
            data_mask_inv = data_mask.max() - data_mask
            if dim == 3:
                data_background = einsum('ijk,ijk->ijk', data_mask_inv,
                                         data_background)
            elif dim == 2:
                data_background = einsum('ij,ij->ij', data_mask_inv,
                                         data_background)
            new_data += data_background

        # set image out
        image_in.setFileName(self.output_filename)
        image_in.data = new_data
        image_in.save()
def create_label_z(fname_seg, z, value):
    """
    Create a label at coordinates x_center, y_center, z
    :param fname_seg: segmentation
    :param z: int
    :return: fname_label
    """
    fname_label = 'labelz.nii.gz'
    nii = Image(fname_seg)
    orientation_origin = nii.change_orientation(
        'RPI')  # change orientation to RPI
    nx, ny, nz, nt, px, py, pz, pt = nii.dim  # Get dimensions
    # find x and y coordinates of the centerline at z using center of mass
    from scipy.ndimage.measurements import center_of_mass
    x, y = center_of_mass(nii.data[:, :, z])
    x, y = int(round(x)), int(round(y))
    nii.data[:, :, :] = 0
    nii.data[x, y, z] = value
    # dilate label to prevent it from disappearing due to nearestneighbor interpolation
    from sct_maths import dilate
    nii.data = dilate(nii.data, [3])
    nii.setFileName(fname_label)
    nii.change_orientation(
        orientation_origin)  # put back in original orientation
    nii.save()
    return fname_label
Exemplo n.º 8
0
def main(args = None):

    dim_list = ['x', 'y', 'z', 't']

    if not args:
        args = sys.argv[1:]

    # Get parser info
    parser = get_parser()
    arguments = parser.parse(sys.argv[1:])
    fname_in = arguments["-i"]
    fname_out = arguments["-o"]
    verbose = int(arguments['-v'])

    # Build fname_out
    if fname_out == '':
        path_in, file_in, ext_in = extract_fname(fname_in)
        fname_out = path_in+file_in+'_mean'+ext_in

    # Open file.
    nii = Image(fname_in)
    data = nii.data

    # run command
    if '-otsu' in arguments:
        param = arguments['-otsu']
        data_out = otsu(data, param)
    elif '-otsu_adap' in arguments:
        param = arguments['-otsu_adap']
        data_out = otsu_adap(data, param[0], param[1])
    elif '-otsu_median' in arguments:
        param = arguments['-otsu_median']
        data_out = otsu_median(data, param[0], param[1])
    elif '-thr' in arguments:
        param = arguments['-thr']
        data_out = threshold(data, param)
    elif '-percent' in arguments:
        param = arguments['-percent']
        data_out = perc(data, param)
    elif '-mean' in arguments:
        dim = dim_list.index(arguments['-mean'])
        data_out = compute_mean(data, dim)
    elif '-std' in arguments:
        dim = dim_list.index(arguments['-std'])
        data_out = compute_std(data, dim)
    elif '-dilate' in arguments:
        data_out = dilate(data, arguments['-dilate'])
    elif '-erode' in arguments:
        data_out = erode(data, arguments['-dilate'])
    else:
        printv('No process applied.', 1, 'warning')
        return

    # Write output
    nii.data = data_out
    nii.setFileName(fname_out)
    nii.save()

    # display message
    printv('Created file:\n--> '+fname_out+'\n', verbose, 'info')
Exemplo n.º 9
0
def concat_data(fname_in, fname_out, dim):
    """
    Concatenate data
    :param fname_in: list of file names.
    :param fname_out:
    :param dim: dimension: 0, 1, 2, 3.
    :return: none
    """
    # create empty list
    list_data = []

    # loop across files
    for i in range(len(fname_in)):
        # append data to list
        list_data.append(Image(fname_in[i]).data)

    # expand dimension of all elements in the list if necessary
    if dim > list_data[0].ndim - 1:
        list_data = [expand_dims(i, dim) for i in list_data]
    # concatenate
    try:
        data_concat = concatenate(list_data, axis=dim)
    except Exception as e:
        sct.printv(
            '\nERROR: Concatenation on line {}'.format(
                sys.exc_info()[-1].tb_lineno) + '\n' + str(e) + '\n', 1,
            'error')

    # write file
    im = Image(fname_in[0])
    im.data = data_concat
    im.setFileName(fname_out)
    im.save()
Exemplo n.º 10
0
def concat_data(fname_in, fname_out, dim):
    """
    Concatenate data
    :param fname_in: list of file names.
    :param fname_out:
    :param dim: dimension: 0, 1, 2, 3.
    :return: none
    """
    # create empty list
    list_data = []

    # loop across files
    for i in range(len(fname_in)):
        # append data to list
        list_data.append(Image(fname_in[i]).data)

    # expand dimension of all elements in the list if necessary
    if dim > list_data[0].ndim-1:
        list_data = [expand_dims(i, dim) for i in list_data]
    # concatenate
    try:
        data_concat = concatenate(list_data, axis=dim)
    except Exception as e:
        sct.printv('\nERROR: Concatenation on line {}'.format(sys.exc_info()[-1].tb_lineno)+'\n'+str(e)+'\n', 1, 'error')

    # write file
    im = Image(fname_in[0])
    im.data = data_concat
    im.setFileName(fname_out)
    im.save()
    def validation(self):
        name_ref_gm_seg = sct.extract_fname(self.ref_gm_seg)
        im_ref_gm_seg = Image('../' + self.ref_gm_seg)

        res_gm_seg_bin = Image('../' + self.res_names['gm_seg'])
        res_wm_seg_bin = Image('../' + self.res_names['wm_seg'])

        sct.run('cp ../' + self.ref_gm_seg + ' ./ref_gm_seg.nii.gz')
        im_ref_wm_seg = inverse_gmseg_to_wmseg(im_ref_gm_seg, Image('../' + self.sc_seg_fname), 'ref_gm_seg')
        im_ref_wm_seg.file_name = 'ref_wm_seg'
        im_ref_wm_seg.ext = '.nii.gz'
        im_ref_wm_seg.save()

        if self.param.res_type == 'prob':
            res_gm_seg_bin.data = np.asarray((res_gm_seg_bin.data >= 0.5).astype(int))
            res_wm_seg_bin.data = np.asarray((res_wm_seg_bin.data >= 0.50001).astype(int))

        res_gm_seg_bin.path = './'
        res_gm_seg_bin.file_name = 'res_gm_seg_bin'
        res_gm_seg_bin.ext = '.nii.gz'
        res_gm_seg_bin.save()
        res_wm_seg_bin.path = './'
        res_wm_seg_bin.file_name = 'res_wm_seg_bin'
        res_wm_seg_bin.ext = '.nii.gz'
        res_wm_seg_bin.save()
        try:
            status_gm, output_gm = sct.run('sct_dice_coefficient ref_gm_seg.nii.gz res_gm_seg_bin.nii.gz  -2d-slices 2', error_exit='warning', raise_exception=True)
        except Exception:
            sct.run('c3d res_gm_seg_bin.nii.gz  ref_gm_seg.nii.gz -reslice-identity -o ref_in_res_space_gm.nii.gz ')
            status_gm, output_gm = sct.run('sct_dice_coefficient ref_in_res_space_gm.nii.gz res_gm_seg_bin.nii.gz  -2d-slices 2', error_exit='warning')
        try:
            status_wm, output_wm = sct.run('sct_dice_coefficient ref_wm_seg.nii.gz res_wm_seg_bin.nii.gz  -2d-slices 2', error_exit='warning', raise_exception=True)
        except Exception:
            sct.run('c3d res_wm_seg_bin.nii.gz  ref_wm_seg.nii.gz -reslice-identity -o ref_in_res_space_wm.nii.gz ')
            status_wm, output_wm = sct.run('sct_dice_coefficient ref_in_res_space_wm.nii.gz res_wm_seg_bin.nii.gz  -2d-slices 2', error_exit='warning')
        dice_name = 'dice_' + self.param.res_type + '.txt'
        dice_fic = open('../' + dice_name, 'w')
        if self.param.res_type == 'prob':
            dice_fic.write('WARNING : the probabilistic segmentations were binarized with a threshold at 0.5 to compute the dice coefficient \n')
        dice_fic.write('\n--------------------------------------------------------------\nDice coefficient on the Gray Matter segmentation:\n')
        dice_fic.write(output_gm)
        dice_fic.write('\n\n--------------------------------------------------------------\nDice coefficient on the White Matter segmentation:\n')
        dice_fic.write(output_wm)
        dice_fic.close()
        # sct.run(' mv ./' + dice_name + ' ../')

        return dice_name
Exemplo n.º 12
0
def get_minimum_path_nii(fname):
    from msct_image import Image
    data=Image(fname)
    vesselness_data = data.data
    raw_orient=data.change_orientation()
    data.data=get_minimum_path(data.data, invert=1)
    data.change_orientation(raw_orient)
    data.file_name += '_minimalpath'
    data.save()
Exemplo n.º 13
0
def concat_data(fname_in_list, dim, pixdim=None):
    """
    Concatenate data
    :param im_in_list: list of images.
    :param dim: dimension: 0, 1, 2, 3.
    :param pixdim: pixel resolution to join to image header
    :return im_out: concatenated image
    """
    # WARNING: calling concat_data in python instead of in command line causes a non understood issue (results are different with both options)
    from numpy import concatenate, expand_dims

    dat_list = []
    data_concat_list = []

    # check if shape of first image is smaller than asked dim to concatenate along
    # data0 = Image(fname_in_list[0]).data
    # if len(data0.shape) <= dim:
    #     expand_dim = True
    # else:
    #     expand_dim = False

    for i, fname in enumerate(fname_in_list):
        # if there is more than 100 images to concatenate, then it does it iteratively to avoid memory issue.
        if i != 0 and i % 100 == 0:
            data_concat_list.append(concatenate(dat_list, axis=dim))
            im = Image(fname)
            dat = im.data
            # if image shape is smaller than asked dim, then expand dim
            if len(dat.shape) <= dim:
                dat = expand_dims(dat, dim)
            dat_list = [dat]
            del im
            del dat
        else:
            im = Image(fname)
            dat = im.data
            # if image shape is smaller than asked dim, then expand dim
            if len(dat.shape) <= dim:
                dat = expand_dims(dat, dim)
            dat_list.append(dat)
            del im
            del dat
    if data_concat_list:
        data_concat_list.append(concatenate(dat_list, axis=dim))
        data_concat = concatenate(data_concat_list, axis=dim)
    else:
        data_concat = concatenate(dat_list, axis=dim)
    # write file
    im_out = Image(fname_in_list[0]).copy()
    im_out.data = data_concat
    im_out.setFileName(im_out.file_name + '_concat' + im_out.ext)

    if pixdim is not None:
        im_out.hdr['pixdim'] = pixdim

    return im_out
def get_minimum_path_nii(fname):
    from msct_image import Image
    data = Image(fname)
    vesselness_data = data.data
    raw_orient = data.change_orientation()
    result, J1, J2 = get_minimum_path(data.data, invert=1)
    data.data = result
    data.change_orientation(raw_orient)
    data.file_name += '_minimalpath'
    data.save()
Exemplo n.º 15
0
def concat_data(fname_in_list, dim, pixdim=None):
    """
    Concatenate data
    :param im_in_list: list of images.
    :param dim: dimension: 0, 1, 2, 3.
    :param pixdim: pixel resolution to join to image header
    :return im_out: concatenated image
    """
    # WARNING: calling concat_data in python instead of in command line causes a non understood issue (results are different with both options)
    from numpy import concatenate, expand_dims, squeeze

    dat_list = []
    data_concat_list = []

    # check if shape of first image is smaller than asked dim to concatenate along
    data0 = Image(fname_in_list[0]).data
    if len(data0.shape) <= dim:
        expand_dim = True
    else:
        expand_dim = False

    for i, fname in enumerate(fname_in_list):
        # if there is more than 100 images to concatenate, then it does it iteratively to avoid memory issue.
        if i != 0 and i % 100 == 0:
            data_concat_list.append(concatenate(dat_list, axis=dim))
            im = Image(fname)
            dat = im.data
            if expand_dim:
                dat = expand_dims(dat, dim)
            dat_list = [dat]
            del im
            del dat
        else:
            im = Image(fname)
            dat = im.data
            if expand_dim:
                dat = expand_dims(dat, dim)
            dat_list.append(dat)
            del im
            del dat
    if data_concat_list:
        data_concat_list.append(concatenate(dat_list, axis=dim))
        data_concat = concatenate(data_concat_list, axis=dim)
    else:
        data_concat = concatenate(dat_list, axis=dim)
    # write file
    im_out = Image(fname_in_list[0]).copy()
    im_out.data = data_concat
    im_out.setFileName(im_out.file_name+'_concat'+im_out.ext)

    if pixdim is not None:
        im_out.hdr['pixdim'] = pixdim

    return im_out
Exemplo n.º 16
0
def copy_header(fname_src, fname_dest):
    """
    Copy header
    :param fname_src: source file name
    :param fname_dest: destination file name
    :return:
    """
    nii_src = Image(fname_src)
    data_dest = Image(fname_dest).data
    nii_src.setFileName(fname_dest)
    nii_src.data = data_dest
    nii_src.save()
def copy_header(fname_src, fname_dest):
    """
    Copy header
    :param fname_src: source file name
    :param fname_dest: destination file name
    :return:
    """
    nii_src = Image(fname_src)
    data_dest = Image(fname_dest).data
    nii_src.setFileName(fname_dest)
    nii_src.data = data_dest
    nii_src.save()
    def execute(self):
        """
        This method executes the symmetry detection
        :return: returns the symmetry data
        """
        img = Image(self.input_image)
        raw_orientation = img.change_orientation()
        data = np.squeeze(img.data)
        dim = data.shape
        section_length = dim[1] / self.nb_sections

        result = np.zeros(dim)

        for i in range(0, self.nb_sections):
            if (i + 1) * section_length > dim[1]:
                y_length = (i + 1) * section_length - (
                    (i + 1) * section_length - dim[1])
                result[:, i * section_length:i * section_length +
                       y_length, :] = symmetry_detector_right_left(
                           data[:, i * section_length:i * section_length +
                                y_length, :],
                           cropped_xy=self.crop_xy)
            sym = symmetry_detector_right_left(
                data[:, i * section_length:(i + 1) * section_length, :],
                cropped_xy=self.crop_xy)
            result[:, i * section_length:(i + 1) * section_length, :] = sym

        result_image = Image(img)
        if len(result_image.data) == 4:
            result_image.data = result[:, :, :, np.newaxis]
        else:
            result_image.data = result

        result_image.change_orientation(raw_orientation)

        return result_image.data
 def output_debug_file(self, img, data, file_name):
     """
     This method writes a nifti file that corresponds to a step in the algorithm for easy debug.
     The new nifti file uses the header from the the image passed as parameter
     :param data: data to be written to file
     :param file_name: filename...
     :return: None
     """
     if self.verbose == 2:
         current_folder = os.getcwd()
         # os.chdir(self.path_tmp)
         try:
             img = Image(img)
             img.data = data
             img.change_orientation(self.raw_orientation)
             img.file_name = file_name
             img.save()
         except Exception, e:
             print e
Exemplo n.º 20
0
def post_processing_volume_wise(fname_in):
    """Post processing function."""
    im_in = Image(fname_in)
    data_in = im_in.data.astype(np.int)

    data_in = _remove_blobs(data_in)

    zz_zeros = [
        zz for zz in range(im_in.dim[2])
        if 1 not in list(np.unique(data_in[:, :, zz]))
    ]
    zz_holes = _remove_extrem_holes(zz_zeros, im_in.dim[2] - 1, 0)
    # filling z_holes, i.e. interpolate for z_slice not segmented
    im_in.data = _fill_z_holes(zz_holes, data_in,
                               im_in.dim[6]) if len(zz_holes) else data_in

    im_in.setFileName(fname_in)
    im_in.save()
    del im_in
 def output_debug_file(self, img, data, file_name):
     """
     This method writes a nifti file that corresponds to a step in the algorithm for easy debug.
     The new nifti file uses the header from the the image passed as parameter
     :param data: data to be written to file
     :param file_name: filename...
     :return: None
     """
     if self.produce_output:
         current_folder = os.getcwd()
         os.chdir(self.debug_folder)
         try:
             img = Image(img)
             img.data = data
             img.change_orientation(self.raw_orientation)
             img.file_name = file_name
             img.save()
         except Exception, e:
             print e
         os.chdir(current_folder)
def label_discs(fname_seg_labeled, verbose=1):
    """
    Label discs from labaled_segmentation
    :param fname_seg_labeld: fname of the labeled segmentation
    :param verbose:
    :return:
    """
    # open labeled segmentation
    im_seg_labeled = Image(fname_seg_labeled)
    orientation_native = im_seg_labeled.change_orientation('RPI')
    nx, ny, nz = im_seg_labeled.dim[0], im_seg_labeled.dim[
        1], im_seg_labeled.dim[2]
    data_disc = np.zeros([nx, ny, nz])
    vertebral_level_previous = np.max(im_seg_labeled.data)
    # loop across z
    for iz in range(nz):
        # get 2d slice
        slice = im_seg_labeled.data[:, :, iz]
        # check if at least one voxel is non-zero
        if np.any(slice):
            slice_one = np.copy(slice)
            # set all non-zero values to 1
            slice_one[slice.nonzero()] = 1
            # compute center of mass
            cx, cy = [
                int(x) for x in np.round(center_of_mass(slice_one)).tolist()
            ]
            # retrieve vertebral level
            vertebral_level = slice[cx, cy]
            # if smaller than previous level, then labeled as a disc
            if vertebral_level < vertebral_level_previous:
                # label disc
                # sct.printv('iz='+iz+', disc='+vertebral_level)
                data_disc[cx, cy, iz] = vertebral_level
            # update variable
            vertebral_level_previous = vertebral_level
    # save disc labeled file
    im_seg_labeled.file_name += '_disc'
    im_seg_labeled.data = data_disc
    im_seg_labeled.change_orientation(orientation_native)
    im_seg_labeled.save()
Exemplo n.º 23
0
def label_discs(fname_seg_labeled, verbose=1):
    """
    Label discs from labaled_segmentation
    :param fname_seg_labeld: fname of the labeled segmentation
    :param verbose:
    :return:
    """
    # open labeled segmentation
    im_seg_labeled = Image(fname_seg_labeled)
    orientation_native = im_seg_labeled.change_orientation('RPI')
    nx, ny, nz = im_seg_labeled.dim[0], im_seg_labeled.dim[1], im_seg_labeled.dim[2]
    data_disc = np.zeros([nx, ny, nz])
    vertebral_level_previous = np.max(im_seg_labeled.data)
    # loop across z
    for iz in range(nz):
        # get 2d slice
        slice = im_seg_labeled.data[:, :, iz]
        # check if at least one voxel is non-zero
        if np.any(slice):
            slice_one = np.copy(slice)
            # set all non-zero values to 1
            slice_one[slice.nonzero()] = 1
            # compute center of mass
            cx, cy = [int(x) for x in np.round(center_of_mass(slice_one)).tolist()]
            # retrieve vertebral level
            vertebral_level = slice[cx, cy]
            # if smaller than previous level, then labeled as a disc
            if vertebral_level < vertebral_level_previous:
                # label disc
                # print 'iz='+iz+', disc='+vertebral_level
                data_disc[cx, cy, iz] = vertebral_level
            # update variable
            vertebral_level_previous = vertebral_level
    # save disc labeled file
    im_seg_labeled.file_name += '_disc'
    im_seg_labeled.data = data_disc
    im_seg_labeled.change_orientation(orientation_native)
    im_seg_labeled.save()
Exemplo n.º 24
0
def create_label_z(fname_seg, z, value):
    """
    Create a label at coordinates x_center, y_center, z
    :param fname_seg: segmentation
    :param z: int
    :return: fname_label
    """
    fname_label = 'labelz.nii.gz'
    nii = Image(fname_seg)
    orientation_origin = nii.change_orientation('RPI')  # change orientation to RPI
    nx, ny, nz, nt, px, py, pz, pt = nii.dim  # Get dimensions
    # find x and y coordinates of the centerline at z using center of mass
    from scipy.ndimage.measurements import center_of_mass
    x, y = center_of_mass(nii.data[:, :, z])
    x, y = int(round(x)), int(round(y))
    nii.data[:, :, :] = 0
    nii.data[x, y, z] = value
    # dilate label to prevent it from disappearing due to nearestneighbor interpolation
    from sct_maths import dilate
    nii.data = dilate(nii.data, [3])
    nii.setFileName(fname_label)
    nii.change_orientation(orientation_origin)  # put back in original orientation
    nii.save()
    return fname_label
Exemplo n.º 25
0
def main():
    # Initialization
    fname_data = ''
    suffix_out = '_crop'
    remove_temp_files = param.remove_temp_files
    verbose = param.verbose
    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI
    remove_temp_files = param.remove_temp_files
    
    # Parameters for debug mode
    if param.debug:
        print '\n*** WARNING: DEBUG MODE ON ***\n'
        fname_data = path_sct+'/testing/data/errsm_23/t2/t2.nii.gz'
        remove_temp_files = 0
    else:
        # Check input parameters
        try:
            opts, args = getopt.getopt(sys.argv[1:],'hi:r:v:')
        except getopt.GetoptError:
            usage()
        if not opts:
            usage()
        for opt, arg in opts:
            if opt == '-h':
                usage()
            elif opt in ('-i'):
                fname_data = arg
            elif opt in ('-r'):
                remove_temp_files = int(arg)
            elif opt in ('-v'):
                verbose = int(arg)

    # display usage if a mandatory argument is not provided
    if fname_data == '':
        usage()

    # Check file existence
    sct.printv('\nCheck file existence...', verbose)
    sct.check_file_exist(fname_data, verbose)

    # Get dimensions of data
    sct.printv('\nGet dimensions of data...', verbose)
    nx, ny, nz, nt, px, py, pz, pt = Image(fname_data).dim
    sct.printv('.. '+str(nx)+' x '+str(ny)+' x '+str(nz), verbose)
    # check if 4D data
    if not nt == 1:
        sct.printv('\nERROR in '+os.path.basename(__file__)+': Data should be 3D.\n', 1, 'error')
        sys.exit(2)

    # print arguments
    print '\nCheck parameters:'
    print '  data ................... '+fname_data
    print

    # Extract path/file/extension
    path_data, file_data, ext_data = sct.extract_fname(fname_data)
    path_out, file_out, ext_out = '', file_data+suffix_out, ext_data

    # create temporary folder
    path_tmp = 'tmp.'+time.strftime("%y%m%d%H%M%S")+'/'
    sct.run('mkdir '+path_tmp)

    # copy files into tmp folder
    sct.run('isct_c3d '+fname_data+' -o '+path_tmp+'data.nii')

    # go to tmp folder
    os.chdir(path_tmp)

    # change orientation
    sct.printv('\nChange orientation to RPI...', verbose)
    set_orientation('data.nii', 'RPI', 'data_rpi.nii')

    # get image of medial slab
    sct.printv('\nGet image of medial slab...', verbose)
    image_array = nibabel.load('data_rpi.nii').get_data()
    nx, ny, nz = image_array.shape
    scipy.misc.imsave('image.jpg', image_array[math.floor(nx/2), :, :])

    # Display the image
    sct.printv('\nDisplay image and get cropping region...', verbose)
    fig = plt.figure()
    # fig = plt.gcf()
    # ax = plt.gca()
    ax = fig.add_subplot(111)
    img = mpimg.imread("image.jpg")
    implot = ax.imshow(img.T)
    implot.set_cmap('gray')
    plt.gca().invert_yaxis()
    # mouse callback
    ax.set_title('Left click on the top and bottom of your cropping field.\n Right click to remove last point.\n Close window when your done.')
    line, = ax.plot([], [], 'ro')  # empty line
    cropping_coordinates = LineBuilder(line)
    plt.show()
    # disconnect callback
    # fig.canvas.mpl_disconnect(line)

    # check if user clicked two times
    if len(cropping_coordinates.xs) != 2:
        sct.printv('\nERROR: You have to select two points. Exit program.\n', 1, 'error')
        sys.exit(2)

    # convert coordinates to integer
    zcrop = [int(i) for i in cropping_coordinates.ys]

    # sort coordinates
    zcrop.sort()

    # crop image
    sct.printv('\nCrop image...', verbose)
    nii = Image('data_rpi.nii')
    data_crop = nii.data[:, :, zcrop[0]:zcrop[1]]
    nii.data = data_crop
    nii.setFileName('data_rpi_crop.nii')
    nii.save()

    # come back to parent folder
    os.chdir('..')

    sct.printv('\nGenerate output files...', verbose)
    sct.generate_output_file(path_tmp+'data_rpi_crop.nii', path_out+file_out+ext_out)

    # Remove temporary files
    if remove_temp_files == 1:
        print('\nRemove temporary files...')
        sct.run('rm -rf '+path_tmp)

    # to view results
    print '\nDone! To view results, type:'
    print 'fslview '+path_out+file_out+ext_out+' &'
    print
def create_mask():

    fsloutput = "export FSLOUTPUTTYPE=NIFTI; "  # for faster processing, all outputs are in NIFTI

    # display usage if a mandatory argument is not provided
    if param.fname_data == "" or param.method == "":
        sct.printv("\nERROR: All mandatory arguments are not provided. See usage (add -h).\n", 1, "error")

    # parse argument for method
    method_list = param.method.replace(" ", "").split(",")  # remove spaces and parse with comma
    # method_list = param.method.split(',')  # parse with comma
    method_type = method_list[0]

    # check existence of method type
    if not method_type in param.method_list:
        sct.printv(
            "\nERROR in "
            + os.path.basename(__file__)
            + ': Method "'
            + method_type
            + '" is not recognized. See usage (add -h).\n',
            1,
            "error",
        )

    # check method val
    if not method_type == "center":
        method_val = method_list[1]
    del method_list

    # check existence of shape
    if not param.shape in param.shape_list:
        sct.printv(
            "\nERROR in "
            + os.path.basename(__file__)
            + ': Shape "'
            + param.shape
            + '" is not recognized. See usage (add -h).\n',
            1,
            "error",
        )

    # check existence of input files
    sct.printv("\ncheck existence of input files...", param.verbose)
    sct.check_file_exist(param.fname_data, param.verbose)
    if method_type == "centerline":
        sct.check_file_exist(method_val, param.verbose)

    # check if orientation is RPI
    sct.printv("\nCheck if orientation is RPI...", param.verbose)
    status, output = sct.run("sct_orientation -i " + param.fname_data)
    if not output == "RPI":
        sct.printv(
            "\nERROR in "
            + os.path.basename(__file__)
            + ": Orientation of input image should be RPI. Use sct_orientation to put your image in RPI.\n",
            1,
            "error",
        )

    # display input parameters
    sct.printv("\nInput parameters:", param.verbose)
    sct.printv("  data .................." + param.fname_data, param.verbose)
    sct.printv("  method ................" + method_type, param.verbose)

    # Extract path/file/extension
    path_data, file_data, ext_data = sct.extract_fname(param.fname_data)

    # Get output folder and file name
    if param.fname_out == "":
        param.fname_out = param.file_prefix + file_data + ext_data
    # fname_out = os.path.abspath(path_out+file_out+ext_out)

    # create temporary folder
    sct.printv("\nCreate temporary folder...", param.verbose)
    path_tmp = sct.slash_at_the_end("tmp." + time.strftime("%y%m%d%H%M%S"), 1)
    sct.run("mkdir " + path_tmp, param.verbose)

    # Copying input data to tmp folder and convert to nii
    # NB: cannot use c3d here because c3d cannot convert 4D data.
    sct.printv("\nCopying input data to tmp folder and convert to nii...", param.verbose)
    convert(param.fname_data, path_tmp + "data.nii")
    # sct.run('cp '+param.fname_data+' '+path_tmp+'data'+ext_data, param.verbose)
    if method_type == "centerline":
        convert(method_val, path_tmp + "centerline.nii.gz")
        # sct.run('isct_c3d '+method_val+' -o '+path_tmp+'/centerline.nii.gz')

    # go to tmp folder
    os.chdir(path_tmp)

    # Get dimensions of data
    sct.printv("\nGet dimensions of data...", param.verbose)
    nx, ny, nz, nt, px, py, pz, pt = Image("data.nii").dim
    sct.printv("  " + str(nx) + " x " + str(ny) + " x " + str(nz) + " x " + str(nt), param.verbose)
    # in case user input 4d data
    if nt != 1:
        sct.printv(
            "WARNING in " + os.path.basename(__file__) + ": Input image is 4d but output mask will 3D.",
            param.verbose,
            "warning",
        )
        # extract first volume to have 3d reference
        nii = Image("data.nii")
        data3d = nii.data[:, :, :, 0]
        nii.data = data3d
        nii.save()

    if method_type == "coord":
        # parse to get coordinate
        coord = map(int, method_val.split("x"))

    if method_type == "point":
        # get file name
        fname_point = method_val
        # extract coordinate of point
        sct.printv("\nExtract coordinate of point...", param.verbose)
        status, output = sct.run("sct_label_utils -i " + fname_point + " -t display-voxel", param.verbose)
        # parse to get coordinate
        coord = output[output.find("Position=") + 10 : -17].split(",")

    if method_type == "center":
        # set coordinate at center of FOV
        coord = round(float(nx) / 2), round(float(ny) / 2)

    if method_type == "centerline":
        # get name of centerline from user argument
        fname_centerline = "centerline.nii.gz"
    else:
        # generate volume with line along Z at coordinates 'coord'
        sct.printv("\nCreate line...", param.verbose)
        fname_centerline = create_line("data.nii", coord, nz)

    # create mask
    sct.printv("\nCreate mask...", param.verbose)
    centerline = nibabel.load(fname_centerline)  # open centerline
    hdr = centerline.get_header()  # get header
    hdr.set_data_dtype("uint8")  # set imagetype to uint8
    data_centerline = centerline.get_data()  # get centerline
    z_centerline = [iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any()]
    nz = len(z_centerline)
    # get center of mass of the centerline
    cx = [0] * nz
    cy = [0] * nz
    for iz in range(0, nz, 1):
        cx[iz], cy[iz] = ndimage.measurements.center_of_mass(numpy.array(data_centerline[:, :, z_centerline[iz]]))
    # create 2d masks
    file_mask = "data_mask"
    for iz in range(nz):
        center = numpy.array([cx[iz], cy[iz]])
        mask2d = create_mask2d(center, param.shape, param.size, nx, ny)
        # Write NIFTI volumes
        img = nibabel.Nifti1Image(mask2d, None, hdr)
        nibabel.save(img, (file_mask + str(iz) + ".nii"))
    # merge along Z
    # cmd = 'fslmerge -z mask '
    cmd = "sct_concat_data -dim z -o mask.nii.gz -i "
    for iz in range(nz):
        cmd = cmd + file_mask + str(iz) + ".nii,"
    # remove ',' at the end of the string
    cmd = cmd[:-1]
    status, output = sct.run(cmd, param.verbose)

    # copy geometry
    copy_header("data.nii", "mask.nii.gz")

    # come back to parent folder
    os.chdir("..")

    # Generate output files
    sct.printv("\nGenerate output files...", param.verbose)
    sct.generate_output_file(path_tmp + "mask.nii.gz", param.fname_out)

    # Remove temporary files
    if param.remove_tmp_files == 1:
        sct.printv("\nRemove temporary files...", param.verbose)
        sct.run("rm -rf " + path_tmp, param.verbose)

    # to view results
    sct.printv("\nDone! To view results, type:", param.verbose)
    sct.printv("fslview " + param.fname_data + " " + param.fname_out + " -l Red -t 0.5 &", param.verbose, "info")
    print
Exemplo n.º 27
0
def create_mask():
    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; '  # for faster processing, all outputs are in NIFTI

    # parse argument for method
    method_type = param.process[0]
    # check method val
    if not method_type == 'center':
        method_val = param.process[1]

    # check existence of input files
    if method_type == 'centerline':
        sct.check_file_exist(method_val, param.verbose)

    # check if orientation is RPI
    sct.printv('\nCheck if orientation is RPI...', param.verbose)
    ori = get_orientation(param.fname_data, filename=True)
    if not ori == 'RPI':
        sct.printv('\nERROR in '+os.path.basename(__file__)+': Orientation of input image should be RPI. Use sct_image -setorient to put your image in RPI.\n', 1, 'error')

    # Extract path/file/extension
    path_data, file_data, ext_data = sct.extract_fname(param.fname_data)

    # Get output folder and file name
    if param.fname_out == '':
        param.fname_out = param.file_prefix+file_data+ext_data
    #fname_out = os.path.abspath(path_out+file_out+ext_out)

    # create temporary folder
    sct.printv('\nCreate temporary folder...', param.verbose)
    path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1)
    sct.run('mkdir '+path_tmp, param.verbose)

    # Copying input data to tmp folder and convert to nii
    sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose)
    convert(param.fname_data, path_tmp+'data.nii')
    # sct.run('cp '+param.fname_data+' '+path_tmp+'data'+ext_data, param.verbose)
    if method_type == 'centerline':
        convert(method_val, path_tmp+'centerline.nii.gz')

    # go to tmp folder
    os.chdir(path_tmp)

    # Get dimensions of data
    sct.printv('\nGet dimensions of data...', param.verbose)
    nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim
    sct.printv('  ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz)+ ' x ' + str(nt), param.verbose)
    # in case user input 4d data
    if nt != 1:
        sct.printv('WARNING in '+os.path.basename(__file__)+': Input image is 4d but output mask will 3D.', param.verbose, 'warning')
        # extract first volume to have 3d reference
        nii = Image('data.nii')
        data3d = nii.data[:,:,:,0]
        nii.data = data3d
        nii.save()

    if method_type == 'coord':
        # parse to get coordinate
        coord = map(int, method_val.split('x'))

    if method_type == 'point':
        # get file name
        fname_point = method_val
        # extract coordinate of point
        sct.printv('\nExtract coordinate of point...', param.verbose)
        status, output = sct.run('sct_label_utils -i '+fname_point+' -p display-voxel', param.verbose)
        # parse to get coordinate
        coord = output[output.find('Position=')+10:-17].split(',')

    if method_type == 'center':
        # set coordinate at center of FOV
        coord = round(float(nx)/2), round(float(ny)/2)

    if method_type == 'centerline':
        # get name of centerline from user argument
        fname_centerline = 'centerline.nii.gz'
    else:
        # generate volume with line along Z at coordinates 'coord'
        sct.printv('\nCreate line...', param.verbose)
        fname_centerline = create_line('data.nii', coord, nz)

    # create mask
    sct.printv('\nCreate mask...', param.verbose)
    centerline = nibabel.load(fname_centerline)  # open centerline
    hdr = centerline.get_header()  # get header
    hdr.set_data_dtype('uint8')  # set imagetype to uint8
    data_centerline = centerline.get_data()  # get centerline
    z_centerline = [iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any()]
    nz = len(z_centerline)
    # get center of mass of the centerline
    cx = [0] * nz
    cy = [0] * nz
    for iz in range(0, nz, 1):
        cx[iz], cy[iz] = ndimage.measurements.center_of_mass(numpy.array(data_centerline[:, :, z_centerline[iz]]))
    # create 2d masks
    file_mask = 'data_mask'
    for iz in range(nz):
        center = numpy.array([cx[iz], cy[iz]])
        mask2d = create_mask2d(center, param.shape, param.size, nx, ny, param.even)
        # Write NIFTI volumes
        img = nibabel.Nifti1Image(mask2d, None, hdr)
        nibabel.save(img, (file_mask+str(iz)+'.nii'))
    # merge along Z
    # cmd = 'fslmerge -z mask '
    im_list = []
    for iz in range(nz):
        im_list.append(Image(file_mask+str(iz)+'.nii'))
    im_out = concat_data(im_list, 2)
    im_out.setFileName('mask.nii.gz')
    im_out.save()

    # copy geometry
    im_dat = Image('data.nii')
    im_mask = Image('mask.nii.gz')
    im_mask = copy_header(im_dat, im_mask)
    im_mask.save()

    # come back to parent folder
    os.chdir('..')

    # Generate output files
    sct.printv('\nGenerate output files...', param.verbose)
    sct.generate_output_file(path_tmp+'mask.nii.gz', param.fname_out)

    # Remove temporary files
    if param.remove_tmp_files == 1:
        sct.printv('\nRemove temporary files...', param.verbose)
        sct.run('rm -rf '+path_tmp, param.verbose, error_exit='warning')

    # to view results
    sct.printv('\nDone! To view results, type:', param.verbose)
    sct.printv('fslview '+param.fname_data+' '+param.fname_out+' -l Red -t 0.5 &', param.verbose, 'info')
    print
def main():

    # get default parameters
    step1 = Paramreg(step='1', type='seg', algo='slicereg', metric='MeanSquares', iter='10')
    step2 = Paramreg(step='2', type='im', algo='syn', metric='MI', iter='3')
    # step1 = Paramreg()
    paramreg = ParamregMultiStep([step1, step2])

    # step1 = Paramreg_step(step='1', type='seg', algo='bsplinesyn', metric='MeanSquares', iter='10', shrink='1', smooth='0', gradStep='0.5')
    # step2 = Paramreg_step(step='2', type='im', algo='syn', metric='MI', iter='10', shrink='1', smooth='0', gradStep='0.5')
    # paramreg = ParamregMultiStep([step1, step2])

    # Initialize the parser
    parser = Parser(__file__)
    parser.usage.set_description('Register anatomical image to the template.')
    parser.add_option(name="-i",
                      type_value="file",
                      description="Anatomical image.",
                      mandatory=True,
                      example="anat.nii.gz")
    parser.add_option(name="-s",
                      type_value="file",
                      description="Spinal cord segmentation.",
                      mandatory=True,
                      example="anat_seg.nii.gz")
    parser.add_option(name="-l",
                      type_value="file",
                      description="Labels. See: http://sourceforge.net/p/spinalcordtoolbox/wiki/create_labels/",
                      mandatory=True,
                      default_value='',
                      example="anat_labels.nii.gz")
    parser.add_option(name="-t",
                      type_value="folder",
                      description="Path to MNI-Poly-AMU template.",
                      mandatory=False,
                      default_value=param.path_template)
    parser.add_option(name="-p",
                      type_value=[[':'], 'str'],
                      description="""Parameters for registration (see sct_register_multimodal). Default:\n--\nstep=1\ntype="""+paramreg.steps['1'].type+"""\nalgo="""+paramreg.steps['1'].algo+"""\nmetric="""+paramreg.steps['1'].metric+"""\npoly="""+paramreg.steps['1'].poly+"""\n--\nstep=2\ntype="""+paramreg.steps['2'].type+"""\nalgo="""+paramreg.steps['2'].algo+"""\nmetric="""+paramreg.steps['2'].metric+"""\niter="""+paramreg.steps['2'].iter+"""\nshrink="""+paramreg.steps['2'].shrink+"""\nsmooth="""+paramreg.steps['2'].smooth+"""\ngradStep="""+paramreg.steps['2'].gradStep+"""\n--""",
                      mandatory=False,
                      example="step=2,type=seg,algo=bsplinesyn,metric=MeanSquares,iter=5,shrink=2:step=3,type=im,algo=syn,metric=MI,iter=5,shrink=1,gradStep=0.3")
    parser.add_option(name="-r",
                      type_value="multiple_choice",
                      description="""Remove temporary files.""",
                      mandatory=False,
                      default_value='1',
                      example=['0', '1'])
    parser.add_option(name="-v",
                      type_value="multiple_choice",
                      description="""Verbose. 0: nothing. 1: basic. 2: extended.""",
                      mandatory=False,
                      default_value=param.verbose,
                      example=['0', '1', '2'])
    if param.debug:
        print '\n*** WARNING: DEBUG MODE ON ***\n'
        fname_data = '/Users/julien/data/temp/sct_example_data/t2/t2.nii.gz'
        fname_landmarks = '/Users/julien/data/temp/sct_example_data/t2/labels.nii.gz'
        fname_seg = '/Users/julien/data/temp/sct_example_data/t2/t2_seg.nii.gz'
        path_template = param.path_template
        remove_temp_files = 0
        verbose = 2
        # speed = 'superfast'
        #param_reg = '2,BSplineSyN,0.6,MeanSquares'
    else:
        arguments = parser.parse(sys.argv[1:])

        # get arguments
        fname_data = arguments['-i']
        fname_seg = arguments['-s']
        fname_landmarks = arguments['-l']
        path_template = arguments['-t']
        remove_temp_files = int(arguments['-r'])
        verbose = int(arguments['-v'])
        if '-p' in arguments:
            paramreg_user = arguments['-p']
            # update registration parameters
            for paramStep in paramreg_user:
                paramreg.addStep(paramStep)

    # initialize other parameters
    file_template = param.file_template
    file_template_label = param.file_template_label
    file_template_seg = param.file_template_seg
    output_type = param.output_type
    zsubsample = param.zsubsample
    # smoothing_sigma = param.smoothing_sigma

    # start timer
    start_time = time.time()

    # get absolute path - TO DO: remove! NEVER USE ABSOLUTE PATH...
    path_template = os.path.abspath(path_template)

    # get fname of the template + template objects
    fname_template = sct.slash_at_the_end(path_template, 1)+file_template
    fname_template_label = sct.slash_at_the_end(path_template, 1)+file_template_label
    fname_template_seg = sct.slash_at_the_end(path_template, 1)+file_template_seg

    # check file existence
    sct.printv('\nCheck template files...')
    sct.check_file_exist(fname_template, verbose)
    sct.check_file_exist(fname_template_label, verbose)
    sct.check_file_exist(fname_template_seg, verbose)

    # print arguments
    sct.printv('\nCheck parameters:', verbose)
    sct.printv('.. Data:                 '+fname_data, verbose)
    sct.printv('.. Landmarks:            '+fname_landmarks, verbose)
    sct.printv('.. Segmentation:         '+fname_seg, verbose)
    sct.printv('.. Path template:        '+path_template, verbose)
    sct.printv('.. Output type:          '+str(output_type), verbose)
    sct.printv('.. Remove temp files:    '+str(remove_temp_files), verbose)

    sct.printv('\nParameters for registration:')
    for pStep in range(1, len(paramreg.steps)+1):
        sct.printv('Step #'+paramreg.steps[str(pStep)].step, verbose)
        sct.printv('.. Type #'+paramreg.steps[str(pStep)].type, verbose)
        sct.printv('.. Algorithm................ '+paramreg.steps[str(pStep)].algo, verbose)
        sct.printv('.. Metric................... '+paramreg.steps[str(pStep)].metric, verbose)
        sct.printv('.. Number of iterations..... '+paramreg.steps[str(pStep)].iter, verbose)
        sct.printv('.. Shrink factor............ '+paramreg.steps[str(pStep)].shrink, verbose)
        sct.printv('.. Smoothing factor......... '+paramreg.steps[str(pStep)].smooth, verbose)
        sct.printv('.. Gradient step............ '+paramreg.steps[str(pStep)].gradStep, verbose)
        sct.printv('.. Degree of polynomial..... '+paramreg.steps[str(pStep)].poly, verbose)

    path_data, file_data, ext_data = sct.extract_fname(fname_data)

    sct.printv('\nCheck input labels...')
    # check if label image contains coherent labels
    image_label = Image(fname_landmarks)
    # -> all labels must be different
    labels = image_label.getNonZeroCoordinates(sorting='value')
    hasDifferentLabels = True
    for lab in labels:
        for otherlabel in labels:
            if lab != otherlabel and lab.hasEqualValue(otherlabel):
                hasDifferentLabels = False
                break
    if not hasDifferentLabels:
        sct.printv('ERROR: Wrong landmarks input. All labels must be different.', verbose, 'error')
    # all labels must be available in tempalte
    image_label_template = Image(fname_template_label)
    labels_template = image_label_template.getNonZeroCoordinates(sorting='value')
    if labels[-1].value > labels_template[-1].value:
        sct.printv('ERROR: Wrong landmarks input. Labels must have correspondance in tempalte space. \nLabel max '
                   'provided: ' + str(labels[-1].value) + '\nLabel max from template: ' +
                   str(labels_template[-1].value), verbose, 'error')


    # create temporary folder
    sct.printv('\nCreate temporary folder...', verbose)
    path_tmp = 'tmp.'+time.strftime("%y%m%d%H%M%S")
    status, output = sct.run('mkdir '+path_tmp)

    # copy files to temporary folder
    sct.printv('\nCopy files...', verbose)
    sct.run('isct_c3d '+fname_data+' -o '+path_tmp+'/data.nii')
    sct.run('isct_c3d '+fname_landmarks+' -o '+path_tmp+'/landmarks.nii.gz')
    sct.run('isct_c3d '+fname_seg+' -o '+path_tmp+'/segmentation.nii.gz')
    sct.run('isct_c3d '+fname_template+' -o '+path_tmp+'/template.nii')
    sct.run('isct_c3d '+fname_template_label+' -o '+path_tmp+'/template_labels.nii.gz')
    sct.run('isct_c3d '+fname_template_seg+' -o '+path_tmp+'/template_seg.nii.gz')

    # go to tmp folder
    os.chdir(path_tmp)

    # resample data to 1mm isotropic
    sct.printv('\nResample data to 1mm isotropic...', verbose)
    sct.run('isct_c3d data.nii -resample-mm 1.0x1.0x1.0mm -interpolation Linear -o datar.nii')
    sct.run('isct_c3d segmentation.nii.gz -resample-mm 1.0x1.0x1.0mm -interpolation NearestNeighbor -o segmentationr.nii.gz')
    # N.B. resampling of labels is more complicated, because they are single-point labels, therefore resampling with neighrest neighbour can make them disappear. Therefore a more clever approach is required.
    resample_labels('landmarks.nii.gz', 'datar.nii', 'landmarksr.nii.gz')
    # # TODO
    # sct.run('sct_label_utils -i datar.nii -t create -x 124,186,19,2:129,98,23,8 -o landmarksr.nii.gz')

    # Change orientation of input images to RPI
    sct.printv('\nChange orientation of input images to RPI...', verbose)
    set_orientation('datar.nii', 'RPI', 'data_rpi.nii')
    set_orientation('landmarksr.nii.gz', 'RPI', 'landmarks_rpi.nii.gz')
    set_orientation('segmentationr.nii.gz', 'RPI', 'segmentation_rpi.nii.gz')

    # # Change orientation of input images to RPI
    # sct.printv('\nChange orientation of input images to RPI...', verbose)
    # set_orientation('data.nii', 'RPI', 'data_rpi.nii')
    # set_orientation('landmarks.nii.gz', 'RPI', 'landmarks_rpi.nii.gz')
    # set_orientation('segmentation.nii.gz', 'RPI', 'segmentation_rpi.nii.gz')

    # get landmarks in native space
    # crop segmentation
    # output: segmentation_rpi_crop.nii.gz
    sct.run('sct_crop_image -i segmentation_rpi.nii.gz -o segmentation_rpi_crop.nii.gz -dim 2 -bzmax')

    # straighten segmentation
    sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose)
    sct.run('sct_straighten_spinalcord -i segmentation_rpi_crop.nii.gz -c segmentation_rpi_crop.nii.gz -r 0 -v '+str(verbose), verbose)
    # re-define warping field using non-cropped space (to avoid issue #367)
    sct.run('sct_concat_transfo -w warp_straight2curve.nii.gz -d data_rpi.nii -o warp_straight2curve.nii.gz')

    # Label preparation:
    # --------------------------------------------------------------------------------
    # Remove unused label on template. Keep only label present in the input label image
    sct.printv('\nRemove unused label on template. Keep only label present in the input label image...', verbose)
    sct.run('sct_label_utils -t remove -i template_labels.nii.gz -o template_label.nii.gz -r landmarks_rpi.nii.gz')

    # Make sure landmarks are INT
    sct.printv('\nConvert landmarks to INT...', verbose)
    sct.run('isct_c3d template_label.nii.gz -type int -o template_label.nii.gz', verbose)

    # Create a cross for the template labels - 5 mm
    sct.printv('\nCreate a 5 mm cross for the template labels...', verbose)
    sct.run('sct_label_utils -t cross -i template_label.nii.gz -o template_label_cross.nii.gz -c 5')

    # Create a cross for the input labels and dilate for straightening preparation - 5 mm
    sct.printv('\nCreate a 5mm cross for the input labels and dilate for straightening preparation...', verbose)
    sct.run('sct_label_utils -t cross -i landmarks_rpi.nii.gz -o landmarks_rpi_cross3x3.nii.gz -c 5 -d')

    # Apply straightening to labels
    sct.printv('\nApply straightening to labels...', verbose)
    sct.run('sct_apply_transfo -i landmarks_rpi_cross3x3.nii.gz -o landmarks_rpi_cross3x3_straight.nii.gz -d segmentation_rpi_crop_straight.nii.gz -w warp_curve2straight.nii.gz -x nn')

    # Convert landmarks from FLOAT32 to INT
    sct.printv('\nConvert landmarks from FLOAT32 to INT...', verbose)
    sct.run('isct_c3d landmarks_rpi_cross3x3_straight.nii.gz -type int -o landmarks_rpi_cross3x3_straight.nii.gz')

    # Remove labels that do not correspond with each others.
    sct.printv('\nRemove labels that do not correspond with each others.', verbose)
    sct.run('sct_label_utils -t remove-symm -i landmarks_rpi_cross3x3_straight.nii.gz -o landmarks_rpi_cross3x3_straight.nii.gz,template_label_cross.nii.gz -r template_label_cross.nii.gz')

    # Estimate affine transfo: straight --> template (landmark-based)'
    sct.printv('\nEstimate affine transfo: straight anat --> template (landmark-based)...', verbose)
    # converting landmarks straight and curved to physical coordinates
    image_straight = Image('landmarks_rpi_cross3x3_straight.nii.gz')
    landmark_straight = image_straight.getNonZeroCoordinates(sorting='value')
    image_template = Image('template_label_cross.nii.gz')
    landmark_template = image_template.getNonZeroCoordinates(sorting='value')
    # Reorganize landmarks
    points_fixed, points_moving = [], []
    landmark_straight_mean = []
    for coord in landmark_straight:
        if coord.value not in [c.value for c in landmark_straight_mean]:
            temp_landmark = coord
            temp_number = 1
            for other_coord in landmark_straight:
                if coord.hasEqualValue(other_coord) and coord != other_coord:
                    temp_landmark += other_coord
                    temp_number += 1
            landmark_straight_mean.append(temp_landmark / temp_number)

    for coord in landmark_straight_mean:
        point_straight = image_straight.transfo_pix2phys([[coord.x, coord.y, coord.z]])
        points_moving.append([point_straight[0][0], point_straight[0][1], point_straight[0][2]])
    for coord in landmark_template:
        point_template = image_template.transfo_pix2phys([[coord.x, coord.y, coord.z]])
        points_fixed.append([point_template[0][0], point_template[0][1], point_template[0][2]])

    # Register curved landmarks on straight landmarks based on python implementation
    sct.printv('\nComputing rigid transformation (algo=translation-scaling-z) ...', verbose)
    import msct_register_landmarks
    (rotation_matrix, translation_array, points_moving_reg, points_moving_barycenter) = \
        msct_register_landmarks.getRigidTransformFromLandmarks(
            points_fixed, points_moving, constraints='translation-scaling-z', show=False)

    # writing rigid transformation file
    text_file = open("straight2templateAffine.txt", "w")
    text_file.write("#Insight Transform File V1.0\n")
    text_file.write("#Transform 0\n")
    text_file.write("Transform: FixedCenterOfRotationAffineTransform_double_3_3\n")
    text_file.write("Parameters: %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f\n" % (
        1.0/rotation_matrix[0, 0], rotation_matrix[0, 1],     rotation_matrix[0, 2],
        rotation_matrix[1, 0],     1.0/rotation_matrix[1, 1], rotation_matrix[1, 2],
        rotation_matrix[2, 0],     rotation_matrix[2, 1],     1.0/rotation_matrix[2, 2],
        translation_array[0, 0],   translation_array[0, 1],   -translation_array[0, 2]))
    text_file.write("FixedParameters: %.9f %.9f %.9f\n" % (points_moving_barycenter[0],
                                                           points_moving_barycenter[1],
                                                           points_moving_barycenter[2]))
    text_file.close()

    # Apply affine transformation: straight --> template
    sct.printv('\nApply affine transformation: straight --> template...', verbose)
    sct.run('sct_concat_transfo -w warp_curve2straight.nii.gz,straight2templateAffine.txt -d template.nii -o warp_curve2straightAffine.nii.gz')
    sct.run('sct_apply_transfo -i data_rpi.nii -o data_rpi_straight2templateAffine.nii -d template.nii -w warp_curve2straightAffine.nii.gz')
    sct.run('sct_apply_transfo -i segmentation_rpi.nii.gz -o segmentation_rpi_straight2templateAffine.nii.gz -d template.nii -w warp_curve2straightAffine.nii.gz -x linear')

    # threshold to 0.5
    nii = Image('segmentation_rpi_straight2templateAffine.nii.gz')
    data = nii.data
    data[data < 0.5] = 0
    nii.data = data
    nii.setFileName('segmentation_rpi_straight2templateAffine_th.nii.gz')
    nii.save()
    # find min-max of anat2template (for subsequent cropping)
    zmin_template, zmax_template = find_zmin_zmax('segmentation_rpi_straight2templateAffine_th.nii.gz')

    # crop template in z-direction (for faster processing)
    sct.printv('\nCrop data in template space (for faster processing)...', verbose)
    sct.run('sct_crop_image -i template.nii -o template_crop.nii -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template))
    sct.run('sct_crop_image -i template_seg.nii.gz -o template_seg_crop.nii.gz -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template))
    sct.run('sct_crop_image -i data_rpi_straight2templateAffine.nii -o data_rpi_straight2templateAffine_crop.nii -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template))
    sct.run('sct_crop_image -i segmentation_rpi_straight2templateAffine.nii.gz -o segmentation_rpi_straight2templateAffine_crop.nii.gz -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template))
    # sub-sample in z-direction
    sct.printv('\nSub-sample in z-direction (for faster processing)...', verbose)
    sct.run('sct_resample -i template_crop.nii -o template_crop_r.nii -f 1x1x'+zsubsample, verbose)
    sct.run('sct_resample -i template_seg_crop.nii.gz -o template_seg_crop_r.nii.gz -f 1x1x'+zsubsample, verbose)
    sct.run('sct_resample -i data_rpi_straight2templateAffine_crop.nii -o data_rpi_straight2templateAffine_crop_r.nii -f 1x1x'+zsubsample, verbose)
    sct.run('sct_resample -i segmentation_rpi_straight2templateAffine_crop.nii.gz -o segmentation_rpi_straight2templateAffine_crop_r.nii.gz -f 1x1x'+zsubsample, verbose)

    # Registration straight spinal cord to template
    sct.printv('\nRegister straight spinal cord to template...', verbose)

    # loop across registration steps
    warp_forward = []
    warp_inverse = []
    for i_step in range(1, len(paramreg.steps)+1):
        sct.printv('\nEstimate transformation for step #'+str(i_step)+'...', verbose)
        # identify which is the src and dest
        if paramreg.steps[str(i_step)].type == 'im':
            src = 'data_rpi_straight2templateAffine_crop_r.nii'
            dest = 'template_crop_r.nii'
            interp_step = 'linear'
        elif paramreg.steps[str(i_step)].type == 'seg':
            src = 'segmentation_rpi_straight2templateAffine_crop_r.nii.gz'
            dest = 'template_seg_crop_r.nii.gz'
            interp_step = 'nn'
        else:
            sct.printv('ERROR: Wrong image type.', 1, 'error')
        # if step>1, apply warp_forward_concat to the src image to be used
        if i_step > 1:
            # sct.run('sct_apply_transfo -i '+src+' -d '+dest+' -w '+','.join(warp_forward)+' -o '+sct.add_suffix(src, '_reg')+' -x '+interp_step, verbose)
            sct.run('sct_apply_transfo -i '+src+' -d '+dest+' -w '+','.join(warp_forward)+' -o '+sct.add_suffix(src, '_reg')+' -x '+interp_step, verbose)
            src = sct.add_suffix(src, '_reg')
        # register src --> dest
        warp_forward_out, warp_inverse_out = register(src, dest, paramreg, param, str(i_step))
        warp_forward.append(warp_forward_out)
        warp_inverse.append(warp_inverse_out)

    # Concatenate transformations:
    sct.printv('\nConcatenate transformations: anat --> template...', verbose)
    sct.run('sct_concat_transfo -w warp_curve2straightAffine.nii.gz,'+','.join(warp_forward)+' -d template.nii -o warp_anat2template.nii.gz', verbose)
    # sct.run('sct_concat_transfo -w warp_curve2straight.nii.gz,straight2templateAffine.txt,'+','.join(warp_forward)+' -d template.nii -o warp_anat2template.nii.gz', verbose)
    warp_inverse.reverse()
    sct.run('sct_concat_transfo -w '+','.join(warp_inverse)+',-straight2templateAffine.txt,warp_straight2curve.nii.gz -d data.nii -o warp_template2anat.nii.gz', verbose)

    # Apply warping fields to anat and template
    if output_type == 1:
        sct.run('sct_apply_transfo -i template.nii -o template2anat.nii.gz -d data.nii -w warp_template2anat.nii.gz -c 1', verbose)
        sct.run('sct_apply_transfo -i data.nii -o anat2template.nii.gz -d template.nii -w warp_anat2template.nii.gz -c 1', verbose)

    # come back to parent folder
    os.chdir('..')

   # Generate output files
    sct.printv('\nGenerate output files...', verbose)
    sct.generate_output_file(path_tmp+'/warp_template2anat.nii.gz', 'warp_template2anat.nii.gz', verbose)
    sct.generate_output_file(path_tmp+'/warp_anat2template.nii.gz', 'warp_anat2template.nii.gz', verbose)
    if output_type == 1:
        sct.generate_output_file(path_tmp+'/template2anat.nii.gz', 'template2anat'+ext_data, verbose)
        sct.generate_output_file(path_tmp+'/anat2template.nii.gz', 'anat2template'+ext_data, verbose)

    # Delete temporary files
    if remove_temp_files:
        sct.printv('\nDelete temporary files...', verbose)
        sct.run('rm -rf '+path_tmp)

    # display elapsed time
    elapsed_time = time.time() - start_time
    sct.printv('\nFinished! Elapsed time: '+str(int(round(elapsed_time)))+'s', verbose)

    # to view results
    sct.printv('\nTo view results, type:', verbose)
    sct.printv('fslview '+fname_data+' template2anat -b 0,4000 &', verbose, 'info')
    sct.printv('fslview '+fname_template+' -b 0,5000 anat2template &\n', verbose, 'info')
Exemplo n.º 29
0
def main(args=None):

    # Initialization
    # fname_anat = ''
    # fname_centerline = ''
    sigma = 3 # default value of the standard deviation for the Gaussian smoothing (in terms of number of voxels)
    # remove_temp_files = param.remove_temp_files
    # verbose = param.verbose
    start_time = time.time()

    parser = get_parser()
    arguments = parser.parse(sys.argv[1:])

    fname_anat = arguments['-i']
    fname_centerline = arguments['-s']
    if '-smooth' in arguments:
        sigma = arguments['-smooth']
    if '-r' in arguments:
        remove_temp_files = int(arguments['-r'])
    if '-v' in arguments:
        verbose = int(arguments['-v'])

    # Display arguments
    print '\nCheck input arguments...'
    print '  Volume to smooth .................. ' + fname_anat
    print '  Centerline ........................ ' + fname_centerline
    print '  Sigma (mm) ........................ '+str(sigma)
    print '  Verbose ........................... '+str(verbose)

    # Check that input is 3D:
    from msct_image import Image
    nx, ny, nz, nt, px, py, pz, pt = Image(fname_anat).dim
    dim = 4  # by default, will be adjusted later
    if nt == 1:
        dim = 3
    if nz == 1:
        dim = 2
    if dim == 4:
        sct.printv('WARNING: the input image is 4D, please split your image to 3D before smoothing spinalcord using :\n'
                   'sct_image -i '+fname_anat+' -split t -o '+fname_anat, verbose, 'warning')
        sct.printv('4D images not supported, aborting ...', verbose, 'error')

    # Extract path/file/extension
    path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat)
    path_centerline, file_centerline, ext_centerline = sct.extract_fname(fname_centerline)

    # create temporary folder
    sct.printv('\nCreate temporary folder...', verbose)
    path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1)
    sct.run('mkdir '+path_tmp, verbose)

    # Copying input data to tmp folder
    sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose)
    sct.run('cp '+fname_anat+' '+path_tmp+'anat'+ext_anat, verbose)
    sct.run('cp '+fname_centerline+' '+path_tmp+'centerline'+ext_centerline, verbose)

    # go to tmp folder
    os.chdir(path_tmp)

    # convert to nii format
    convert('anat'+ext_anat, 'anat.nii')
    convert('centerline'+ext_centerline, 'centerline.nii')

    # Change orientation of the input image into RPI
    print '\nOrient input volume to RPI orientation...'
    fname_anat_rpi = set_orientation('anat.nii', 'RPI', filename=True)
    move(fname_anat_rpi, 'anat_rpi.nii')
    # Change orientation of the input image into RPI
    print '\nOrient centerline to RPI orientation...'
    fname_centerline_rpi = set_orientation('centerline.nii', 'RPI', filename=True)
    move(fname_centerline_rpi, 'centerline_rpi.nii')

    # Straighten the spinal cord
    # straighten segmentation
    sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose)
    # check if warp_curve2straight and warp_straight2curve already exist (i.e. no need to do it another time)
    if os.path.isfile('../warp_curve2straight.nii.gz') and os.path.isfile('../warp_straight2curve.nii.gz') and os.path.isfile('../straight_ref.nii.gz'):
        # if they exist, copy them into current folder
        sct.printv('WARNING: Straightening was already run previously. Copying warping fields...', verbose, 'warning')
        shutil.copy('../warp_curve2straight.nii.gz', 'warp_curve2straight.nii.gz')
        shutil.copy('../warp_straight2curve.nii.gz', 'warp_straight2curve.nii.gz')
        shutil.copy('../straight_ref.nii.gz', 'straight_ref.nii.gz')
        # apply straightening
        sct.run('sct_apply_transfo -i anat_rpi.nii -w warp_curve2straight.nii.gz -d straight_ref.nii.gz -o anat_rpi_straight.nii -x spline', verbose)
    else:
        sct.run('sct_straighten_spinalcord -i anat_rpi.nii -s centerline_rpi.nii -qc 0 -x spline', verbose)

    # Smooth the straightened image along z
    print '\nSmooth the straightened image along z...'
    sct.run('sct_maths -i anat_rpi_straight.nii -smooth 0,0,'+str(sigma)+' -o anat_rpi_straight_smooth.nii', verbose)

    # Apply the reversed warping field to get back the curved spinal cord
    print '\nApply the reversed warping field to get back the curved spinal cord...'
    sct.run('sct_apply_transfo -i anat_rpi_straight_smooth.nii -o anat_rpi_straight_smooth_curved.nii -d anat.nii -w warp_straight2curve.nii.gz -x spline', verbose)

    # replace zeroed voxels by original image (issue #937)
    sct.printv('\nReplace zeroed voxels by original image...', verbose)
    nii_smooth = Image('anat_rpi_straight_smooth_curved.nii')
    data_smooth = nii_smooth.data
    data_input = Image('anat.nii').data
    indzero = np.where(data_smooth == 0)
    data_smooth[indzero] = data_input[indzero]
    nii_smooth.data = data_smooth
    nii_smooth.setFileName('anat_rpi_straight_smooth_curved_nonzero.nii')
    nii_smooth.save()

    # come back to parent folder
    os.chdir('..')

    # Generate output file
    print '\nGenerate output file...'
    sct.generate_output_file(path_tmp+'/anat_rpi_straight_smooth_curved_nonzero.nii', file_anat+'_smooth'+ext_anat)

    # Remove temporary files
    if remove_temp_files == 1:
        print('\nRemove temporary files...')
        sct.run('rm -rf '+path_tmp)

    # Display elapsed time
    elapsed_time = time.time() - start_time
    print '\nFinished! Elapsed time: '+str(int(round(elapsed_time)))+'s\n'

    # to view results
    sct.printv('Done! To view results, type:', verbose)
    sct.printv('fslview '+file_anat+' '+file_anat+'_smooth &\n', verbose, 'info')
Exemplo n.º 30
0
def main():
    # create temporary folder
    sct.printv('\nCreate temporary folder...', verbose, 'normal')
    path_tmp = 'tmp.'+time.strftime("%y%m%d%H%M%S")+'/'
    sct.run('mkdir '+path_tmp)

    target = 'target.nii.gz'
    target_seg = 'target_seg.nii.gz'
    anat = 'anat.nii.gz'
    anat_seg = 'anat_seg.nii.gz'
    warp_template2anat = 'warp_template2anat.nii.gz'

    sct.run('cp '+multimodal_reg_param.anat+' '+path_tmp+anat)
    sct.run('cp '+multimodal_reg_param.target+' '+path_tmp+target)
    sct.run('cp '+multimodal_reg_param.anat_seg+' '+path_tmp+anat_seg)
    sct.run('cp '+multimodal_reg_param.target_seg+' '+path_tmp+target_seg)
    sct.run('cp '+multimodal_reg_param.warp_template2anat+' '+path_tmp+warp_template2anat)

    os.chdir(path_tmp)
    # registration of the template to the target
    warp_anat2target, warp_target2anat, label_original = reg_multimodal_warp(anat, target, anat_seg, target_seg, warp_template2anat, multimodal_reg_param)

    # segmentation of the gray matter
    gm_seg_param.res_type = 'binary'
    wm_fname, gm_fname = segment_gm(target_fname=target, sc_seg_fname=target_seg, path_to_label=label_original, param=gm_seg_param)
    wm_seg_out = sct.extract_fname(multimodal_reg_param.target)[1]+'_wm_seg.nii.gz'
    gm_seg_out = sct.extract_fname(multimodal_reg_param.target)[1]+'_gm_seg.nii.gz'
    sct.run('cp '+wm_fname+' ../'+wm_seg_out)
    sct.run('cp '+gm_fname+' ../'+gm_seg_out)

    # registration of the template WM to the automatic Wm segmentation
    wm_reg_param.fname_fixed = wm_fname
    wm_reg_param.fname_moving = label_original + '/template/MNI-Poly-AMU_WM.nii.gz'
    wm_reg_param.fname_seg_fixed = target_seg
    wm_reg_param.fname_seg_moving = label_original + '/template/MNI-Poly-AMU_cord.nii.gz'

    if gm_seg_param.res_type == 'binary':
        # binarize template WM
        template_wm = Image(wm_reg_param.fname_moving)
        template_wm.data = (template_wm.data > 0.5).astype(int)
        template_wm.save()

    warp, inverse_warp = wm_registration(wm_reg_param)

    warp_anat2target_corrected = 'warp_'+sct.extract_fname(multimodal_reg_param.anat)[1]+'2'+sct.extract_fname(multimodal_reg_param.target)[1]+'_corrected_wm.nii.gz'
    warp_target2anat_corrected = 'warp_'+sct.extract_fname(multimodal_reg_param.target)[1]+'2'+sct.extract_fname(multimodal_reg_param.anat)[1]+'_corrected_wm.nii.gz'

    sct.run('sct_concat_transfo -w '+warp_anat2target+','+warp+' -d '+target+' -o '+warp_anat2target_corrected)
    sct.run('sct_concat_transfo -w '+inverse_warp+','+warp_target2anat+' -d '+anat+' -o '+warp_target2anat_corrected)

    target_reg = sct.extract_fname(multimodal_reg_param.target)[1]+'_reg_corrected.nii.gz'
    anat_reg = sct.extract_fname(multimodal_reg_param.anat)[1]+'_reg_corrected.nii.gz'
    sct.run('sct_apply_transfo -i '+target+' -d '+anat+' -w '+warp_target2anat_corrected+' -o '+target_reg)
    sct.run('sct_apply_transfo -i '+anat+' -d '+target+' -w '+warp_anat2target_corrected+' -o '+anat_reg)

    sct.run('cp '+target_reg+' ../'+target_reg)
    sct.run('cp '+anat_reg+' ../'+anat_reg)
    sct.run('cp '+warp_anat2target_corrected+' ../'+warp_anat2target_corrected)
    sct.run('cp '+warp_target2anat_corrected+' ../'+warp_target2anat_corrected)

    sct.printv('Done!\n'
               'You can warp the template to the target using the following command lines:\n'
               'sct_concat_transfo -w '+multimodal_reg_param.warp_template2anat+','+warp_anat2target_corrected+' -d '+multimodal_reg_param.target+' -o warp_template2'+sct.extract_fname(multimodal_reg_param.target)[1]+'.nii.gz\n'
               'sct_warp_template -d '+multimodal_reg_param.target+' -w warp_template2'+sct.extract_fname(multimodal_reg_param.target)[1]+'.nii.gz', verbose, 'info')
    os.chdir('..')

    if remove:
        sct.printv('\nRemove temporary files...', verbose, 'normal')
        sct.run("rm -rf "+path_tmp)
Exemplo n.º 31
0
    def crop_with_gui(self):
        import matplotlib.pyplot as plt
        import matplotlib.image as mpimg
        # Initialization
        fname_data = self.input_filename
        suffix_out = '_crop'
        remove_temp_files = self.rm_tmp_files
        verbose = self.verbose

        # Check file existence
        sct.printv('\nCheck file existence...', verbose)
        sct.check_file_exist(fname_data, verbose)

        # Get dimensions of data
        sct.printv('\nGet dimensions of data...', verbose)
        nx, ny, nz, nt, px, py, pz, pt = Image(fname_data).dim
        sct.printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz),
                   verbose)
        # check if 4D data
        if not nt == 1:
            sct.printv(
                '\nERROR in ' + os.path.basename(__file__) +
                ': Data should be 3D.\n', 1, 'error')
            sys.exit(2)

        # sct.printv(arguments)
        sct.printv('\nCheck parameters:')
        sct.printv('  data ................... ' + fname_data)

        # Extract path/file/extension
        path_data, file_data, ext_data = sct.extract_fname(fname_data)
        path_out, file_out, ext_out = '', file_data + suffix_out, ext_data

        # create temporary folder
        path_tmp = 'tmp.' + time.strftime("%y%m%d%H%M%S") + '/'
        sct.run('mkdir ' + path_tmp)

        # copy files into tmp folder
        from sct_convert import convert
        sct.printv('\nCopying input data to tmp folder and convert to nii...',
                   verbose)
        convert(fname_data, path_tmp + 'data.nii')

        # go to tmp folder
        os.chdir(path_tmp)

        # change orientation
        sct.printv('\nChange orientation to RPI...', verbose)
        sct.run('sct_image -i data.nii -setorient RPI -o data_rpi.nii')

        # get image of medial slab
        sct.printv('\nGet image of medial slab...', verbose)
        image_array = nibabel.load('data_rpi.nii').get_data()
        nx, ny, nz = image_array.shape
        scipy.misc.imsave('image.jpg', image_array[math.floor(nx / 2), :, :])

        # Display the image
        sct.printv('\nDisplay image and get cropping region...', verbose)
        fig = plt.figure()
        # fig = plt.gcf()
        # ax = plt.gca()
        ax = fig.add_subplot(111)
        img = mpimg.imread("image.jpg")
        implot = ax.imshow(img.T)
        implot.set_cmap('gray')
        plt.gca().invert_yaxis()
        # mouse callback
        ax.set_title(
            'Left click on the top and bottom of your cropping field.\n Right click to remove last point.\n Close window when your done.'
        )
        line, = ax.plot([], [], 'ro')  # empty line
        cropping_coordinates = LineBuilder(line)
        plt.show()
        # disconnect callback
        # fig.canvas.mpl_disconnect(line)

        # check if user clicked two times
        if len(cropping_coordinates.xs) != 2:
            sct.printv(
                '\nERROR: You have to select two points. Exit program.\n', 1,
                'error')
            sys.exit(2)

        # convert coordinates to integer
        zcrop = [int(i) for i in cropping_coordinates.ys]

        # sort coordinates
        zcrop.sort()

        # crop image
        sct.printv('\nCrop image...', verbose)
        nii = Image('data_rpi.nii')
        data_crop = nii.data[:, :, zcrop[0]:zcrop[1]]
        nii.data = data_crop
        nii.setFileName('data_rpi_crop.nii')
        nii.save()

        # come back to parent folder
        os.chdir('..')

        sct.printv('\nGenerate output files...', verbose)
        sct.generate_output_file(path_tmp + 'data_rpi_crop.nii',
                                 path_out + file_out + ext_out)

        # Remove temporary files
        if remove_temp_files == 1:
            sct.printv('\nRemove temporary files...')
            sct.run('rm -rf ' + path_tmp)

        # to view results
        sct.printv('\nDone! To view results, type:')
        sct.printv('fslview ' + path_out + file_out + ext_out + ' &')
        sct.printv()
    def process(self):
        # preprocessing
        os.chdir(self.tmp_dir)
        im_target = Image(self.original_target)
        im_sc_seg = Image(self.original_sc_seg)
        self.original_header = im_target.hdr
        self.original_orientation = im_target.orientation
        index_x = self.original_orientation.find('R') if 'R' in self.original_orientation else self.original_orientation.find('L')
        index_y = self.original_orientation.find('P') if 'P' in self.original_orientation else self.original_orientation.find('A')
        index_z = self.original_orientation.find('I') if 'I' in self.original_orientation else self.original_orientation.find('S')

        # resampling of the images
        nx, ny, nz, nt, px, py, pz, pt = im_target.dim

        pix_dim = [px, py, pz]
        self.original_px = pix_dim[index_x]
        self.original_py = pix_dim[index_y]

        if round(self.original_px, 2) != self.resample_to or round(self.original_py, 2) != self.resample_to:
            self.t2star = resample_image(self.original_target, npx=self.resample_to, npy=self.resample_to)
            self.sc_seg = resample_image(self.original_sc_seg, binary=True, npx=self.resample_to, npy=self.resample_to)

        # denoising (optional)
        im_target = Image(self.t2star)
        if self.denoising:
            from sct_maths import denoise_ornlm
            im_target.data = denoise_ornlm(im_target.data)
            im_target.save()
            self.t2star = im_target.file_name + im_target.ext

        box_size = int(22.5/self.resample_to)

        # Pad in case the spinal cord is too close to the edges
        pad_size = box_size/2 + 2
        self.pad = [str(pad_size)]*3

        self.pad[index_z] = str(0)

        t2star_pad = sct.add_suffix(self.t2star, '_pad')
        sc_seg_pad = sct.add_suffix(self.sc_seg, '_pad')
        sct.run('sct_image -i '+self.t2star+' -pad '+self.pad[0]+','+self.pad[1]+','+self.pad[2]+' -o '+t2star_pad)
        sct.run('sct_image -i '+self.sc_seg+' -pad '+self.pad[0]+','+self.pad[1]+','+self.pad[2]+' -o '+sc_seg_pad)
        self.t2star = t2star_pad
        self.sc_seg = sc_seg_pad

        # put data in RPI
        t2star_rpi = sct.add_suffix(self.t2star, '_RPI')
        sc_seg_rpi = sct.add_suffix(self.sc_seg, '_RPI')
        sct.run('sct_image -i '+self.t2star+' -setorient RPI -o '+t2star_rpi)
        sct.run('sct_image -i '+self.sc_seg+' -setorient RPI -o '+sc_seg_rpi)
        self.t2star = t2star_rpi
        self.sc_seg = sc_seg_rpi

        self.square_mask, self.processed_target = crop_t2_star(self.t2star, self.sc_seg, box_size=box_size)

        if self.t2 is not None:
            self.fname_level = compute_level_file(self.t2star, self.sc_seg, self.t2, self.t2_seg, self.t2_landmarks)
        elif self.fname_level is not None:
            level_orientation = get_orientation(self.fname_level, filename=True)
            if level_orientation != 'IRP':
                self.fname_level = set_orientation(self.fname_level, 'IRP', filename=True)

        os.chdir('..')
def get_centerline_from_point(input_image, point_file, gap=4, gaussian_kernel=4, remove_tmp_files=1):

    # Initialization
    fname_anat = input_image
    fname_point = point_file
    slice_gap = gap
    remove_tmp_files = remove_tmp_files
    gaussian_kernel = gaussian_kernel
    start_time = time()
    verbose = 1

    # get path of the toolbox
    status, path_sct = commands.getstatusoutput("echo $SCT_DIR")
    path_sct = sct.slash_at_the_end(path_sct, 1)

    # Parameters for debug mode
    if param.debug == 1:
        sct.printv("\n*** WARNING: DEBUG MODE ON ***\n\t\t\tCurrent working directory: " + os.getcwd(), "warning")
        status, path_sct_testing_data = commands.getstatusoutput("echo $SCT_TESTING_DATA_DIR")
        fname_anat = path_sct_testing_data + "/t2/t2.nii.gz"
        fname_point = path_sct_testing_data + "/t2/t2_centerline_init.nii.gz"
        slice_gap = 5

    # check existence of input files
    sct.check_file_exist(fname_anat)
    sct.check_file_exist(fname_point)

    # extract path/file/extension
    path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat)
    path_point, file_point, ext_point = sct.extract_fname(fname_point)

    # extract path of schedule file
    # TODO: include schedule file in sct
    # TODO: check existence of schedule file
    file_schedule = path_sct + param.schedule_file

    # Get input image orientation
    input_image_orientation = get_orientation_3d(fname_anat, filename=True)

    # Display arguments
    print "\nCheck input arguments..."
    print "  Anatomical image:     " + fname_anat
    print "  Orientation:          " + input_image_orientation
    print "  Point in spinal cord: " + fname_point
    print "  Slice gap:            " + str(slice_gap)
    print "  Gaussian kernel:      " + str(gaussian_kernel)
    print "  Degree of polynomial: " + str(param.deg_poly)

    # create temporary folder
    print ("\nCreate temporary folder...")
    path_tmp = "tmp." + strftime("%y%m%d%H%M%S")
    sct.create_folder(path_tmp)
    print "\nCopy input data..."
    sct.run("cp " + fname_anat + " " + path_tmp + "/tmp.anat" + ext_anat)
    sct.run("cp " + fname_point + " " + path_tmp + "/tmp.point" + ext_point)

    # go to temporary folder
    os.chdir(path_tmp)

    # convert to nii
    im_anat = convert("tmp.anat" + ext_anat, "tmp.anat.nii")
    im_point = convert("tmp.point" + ext_point, "tmp.point.nii")

    # Reorient input anatomical volume into RL PA IS orientation
    print "\nReorient input volume to RL PA IS orientation..."
    set_orientation(im_anat, "RPI")
    im_anat.setFileName("tmp.anat_orient.nii")
    # Reorient binary point into RL PA IS orientation
    print "\nReorient binary point into RL PA IS orientation..."
    # sct.run(sct.fsloutput + 'fslswapdim tmp.point RL PA IS tmp.point_orient')
    set_orientation(im_point, "RPI")
    im_point.setFileName("tmp.point_orient.nii")

    # Get image dimensions
    print "\nGet image dimensions..."
    nx, ny, nz, nt, px, py, pz, pt = Image("tmp.anat_orient.nii").dim
    print ".. matrix size: " + str(nx) + " x " + str(ny) + " x " + str(nz)
    print ".. voxel size:  " + str(px) + "mm x " + str(py) + "mm x " + str(pz) + "mm"

    # Split input volume
    print "\nSplit input volume..."
    im_anat_split_list = split_data(im_anat, 2)
    file_anat_split = []
    for im in im_anat_split_list:
        file_anat_split.append(im.absolutepath)
        im.save()

    im_point_split_list = split_data(im_point, 2)
    file_point_split = []
    for im in im_point_split_list:
        file_point_split.append(im.absolutepath)
        im.save()

    # Extract coordinates of input point
    data_point = Image("tmp.point_orient.nii").data
    x_init, y_init, z_init = unravel_index(data_point.argmax(), data_point.shape)
    sct.printv("Coordinates of input point: (" + str(x_init) + ", " + str(y_init) + ", " + str(z_init) + ")", verbose)

    # Create 2D gaussian mask
    sct.printv("\nCreate gaussian mask from point...", verbose)
    xx, yy = mgrid[:nx, :ny]
    mask2d = zeros((nx, ny))
    radius = round(float(gaussian_kernel + 1) / 2)  # add 1 because the radius includes the center.
    sigma = float(radius)
    mask2d = exp(-(((xx - x_init) ** 2) / (2 * (sigma ** 2)) + ((yy - y_init) ** 2) / (2 * (sigma ** 2))))

    # Save mask to 2d file
    file_mask_split = ["tmp.mask_orient_Z" + str(z).zfill(4) for z in range(0, nz, 1)]
    nii_mask2d = Image("tmp.anat_orient_Z0000.nii")
    nii_mask2d.data = mask2d
    nii_mask2d.setFileName(file_mask_split[z_init] + ".nii")
    nii_mask2d.save()

    # initialize variables
    file_mat = ["tmp.mat_Z" + str(z).zfill(4) for z in range(0, nz, 1)]
    file_mat_inv = ["tmp.mat_inv_Z" + str(z).zfill(4) for z in range(0, nz, 1)]
    file_mat_inv_cumul = ["tmp.mat_inv_cumul_Z" + str(z).zfill(4) for z in range(0, nz, 1)]

    # create identity matrix for initial transformation matrix
    fid = open(file_mat_inv_cumul[z_init], "w")
    fid.write("%i %i %i %i\n" % (1, 0, 0, 0))
    fid.write("%i %i %i %i\n" % (0, 1, 0, 0))
    fid.write("%i %i %i %i\n" % (0, 0, 1, 0))
    fid.write("%i %i %i %i\n" % (0, 0, 0, 1))
    fid.close()

    # initialize centerline: give value corresponding to initial point
    x_centerline = [x_init]
    y_centerline = [y_init]
    z_centerline = [z_init]
    warning_count = 0

    # go up (1), then down (2) in reference to the binary point
    for iUpDown in range(1, 3):

        if iUpDown == 1:
            # z increases
            slice_gap_signed = slice_gap
        elif iUpDown == 2:
            # z decreases
            slice_gap_signed = -slice_gap
            # reverse centerline (because values will be appended at the end)
            x_centerline.reverse()
            y_centerline.reverse()
            z_centerline.reverse()

        # initialization before looping
        z_dest = z_init  # point given by user
        z_src = z_dest + slice_gap_signed

        # continue looping if 0 <= z < nz
        while 0 <= z_src < nz:

            # print current z:
            print "z=" + str(z_src) + ":"

            # estimate transformation
            sct.run(
                fsloutput
                + "flirt -in "
                + file_anat_split[z_src]
                + " -ref "
                + file_anat_split[z_dest]
                + " -schedule "
                + file_schedule
                + " -verbose 0 -omat "
                + file_mat[z_src]
                + " -cost normcorr -forcescaling -inweight "
                + file_mask_split[z_dest]
                + " -refweight "
                + file_mask_split[z_dest]
            )

            # display transfo
            status, output = sct.run("cat " + file_mat[z_src])
            print output

            # check if transformation is bigger than 1.5x slice_gap
            tx = float(output.split()[3])
            ty = float(output.split()[7])
            norm_txy = linalg.norm([tx, ty], ord=2)
            if norm_txy > 1.5 * slice_gap:
                print "WARNING: Transformation is too large --> using previous one."
                warning_count = warning_count + 1
                # if previous transformation exists, replace current one with previous one
                if os.path.isfile(file_mat[z_dest]):
                    sct.run("cp " + file_mat[z_dest] + " " + file_mat[z_src])

            # estimate inverse transformation matrix
            sct.run("convert_xfm -omat " + file_mat_inv[z_src] + " -inverse " + file_mat[z_src])

            # compute cumulative transformation
            sct.run(
                "convert_xfm -omat "
                + file_mat_inv_cumul[z_src]
                + " -concat "
                + file_mat_inv[z_src]
                + " "
                + file_mat_inv_cumul[z_dest]
            )

            # apply inverse cumulative transformation to initial gaussian mask (to put it in src space)
            sct.run(
                fsloutput
                + "flirt -in "
                + file_mask_split[z_init]
                + " -ref "
                + file_mask_split[z_init]
                + " -applyxfm -init "
                + file_mat_inv_cumul[z_src]
                + " -out "
                + file_mask_split[z_src]
            )

            # open inverse cumulative transformation file and generate centerline
            fid = open(file_mat_inv_cumul[z_src])
            mat = fid.read().split()
            x_centerline.append(x_init + float(mat[3]))
            y_centerline.append(y_init + float(mat[7]))
            z_centerline.append(z_src)
            # z_index = z_index+1

            # define new z_dest (target slice) and new z_src (moving slice)
            z_dest = z_dest + slice_gap_signed
            z_src = z_src + slice_gap_signed

    # Reconstruct centerline
    # ====================================================================================================

    # reverse back centerline (because it's been reversed once, so now all values are in the right order)
    x_centerline.reverse()
    y_centerline.reverse()
    z_centerline.reverse()

    # fit centerline in the Z-X plane using polynomial function
    print "\nFit centerline in the Z-X plane using polynomial function..."
    coeffsx = polyfit(z_centerline, x_centerline, deg=param.deg_poly)
    polyx = poly1d(coeffsx)
    x_centerline_fit = polyval(polyx, z_centerline)
    # calculate RMSE
    rmse = linalg.norm(x_centerline_fit - x_centerline) / sqrt(len(x_centerline))
    # calculate max absolute error
    max_abs = max(abs(x_centerline_fit - x_centerline))
    print ".. RMSE (in mm): " + str(rmse * px)
    print ".. Maximum absolute error (in mm): " + str(max_abs * px)

    # fit centerline in the Z-Y plane using polynomial function
    print "\nFit centerline in the Z-Y plane using polynomial function..."
    coeffsy = polyfit(z_centerline, y_centerline, deg=param.deg_poly)
    polyy = poly1d(coeffsy)
    y_centerline_fit = polyval(polyy, z_centerline)
    # calculate RMSE
    rmse = linalg.norm(y_centerline_fit - y_centerline) / sqrt(len(y_centerline))
    # calculate max absolute error
    max_abs = max(abs(y_centerline_fit - y_centerline))
    print ".. RMSE (in mm): " + str(rmse * py)
    print ".. Maximum absolute error (in mm): " + str(max_abs * py)

    # display
    if param.debug == 1:
        import matplotlib.pyplot as plt

        plt.figure()
        plt.plot(z_centerline, x_centerline, ".", z_centerline, x_centerline_fit, "r")
        plt.legend(["Data", "Polynomial Fit"])
        plt.title("Z-X plane polynomial interpolation")
        plt.show()

        plt.figure()
        plt.plot(z_centerline, y_centerline, ".", z_centerline, y_centerline_fit, "r")
        plt.legend(["Data", "Polynomial Fit"])
        plt.title("Z-Y plane polynomial interpolation")
        plt.show()

    # generate full range z-values for centerline
    z_centerline_full = [iz for iz in range(0, nz, 1)]

    # calculate X and Y values for the full centerline
    x_centerline_fit_full = polyval(polyx, z_centerline_full)
    y_centerline_fit_full = polyval(polyy, z_centerline_full)

    # Generate fitted transformation matrices and write centerline coordinates in text file
    print "\nGenerate fitted transformation matrices and write centerline coordinates in text file..."
    file_mat_inv_cumul_fit = ["tmp.mat_inv_cumul_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)]
    file_mat_cumul_fit = ["tmp.mat_cumul_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)]
    fid_centerline = open("tmp.centerline_coordinates.txt", "w")
    for iz in range(0, nz, 1):
        # compute inverse cumulative fitted transformation matrix
        fid = open(file_mat_inv_cumul_fit[iz], "w")
        fid.write("%i %i %i %f\n" % (1, 0, 0, x_centerline_fit_full[iz] - x_init))
        fid.write("%i %i %i %f\n" % (0, 1, 0, y_centerline_fit_full[iz] - y_init))
        fid.write("%i %i %i %i\n" % (0, 0, 1, 0))
        fid.write("%i %i %i %i\n" % (0, 0, 0, 1))
        fid.close()
        # compute forward cumulative fitted transformation matrix
        sct.run("convert_xfm -omat " + file_mat_cumul_fit[iz] + " -inverse " + file_mat_inv_cumul_fit[iz])
        # write centerline coordinates in x, y, z format
        fid_centerline.write(
            "%f %f %f\n" % (x_centerline_fit_full[iz], y_centerline_fit_full[iz], z_centerline_full[iz])
        )
    fid_centerline.close()

    # Prepare output data
    # ====================================================================================================

    # write centerline as text file
    for iz in range(0, nz, 1):
        # compute inverse cumulative fitted transformation matrix
        fid = open(file_mat_inv_cumul_fit[iz], "w")
        fid.write("%i %i %i %f\n" % (1, 0, 0, x_centerline_fit_full[iz] - x_init))
        fid.write("%i %i %i %f\n" % (0, 1, 0, y_centerline_fit_full[iz] - y_init))
        fid.write("%i %i %i %i\n" % (0, 0, 1, 0))
        fid.write("%i %i %i %i\n" % (0, 0, 0, 1))
        fid.close()

    # write polynomial coefficients
    savetxt("tmp.centerline_polycoeffs_x.txt", coeffsx)
    savetxt("tmp.centerline_polycoeffs_y.txt", coeffsy)

    # apply transformations to data
    print "\nApply fitted transformation matrices..."
    file_anat_split_fit = ["tmp.anat_orient_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)]
    file_mask_split_fit = ["tmp.mask_orient_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)]
    file_point_split_fit = ["tmp.point_orient_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)]
    for iz in range(0, nz, 1):
        # forward cumulative transformation to data
        sct.run(
            fsloutput
            + "flirt -in "
            + file_anat_split[iz]
            + " -ref "
            + file_anat_split[iz]
            + " -applyxfm -init "
            + file_mat_cumul_fit[iz]
            + " -out "
            + file_anat_split_fit[iz]
        )
        # inverse cumulative transformation to mask
        sct.run(
            fsloutput
            + "flirt -in "
            + file_mask_split[z_init]
            + " -ref "
            + file_mask_split[z_init]
            + " -applyxfm -init "
            + file_mat_inv_cumul_fit[iz]
            + " -out "
            + file_mask_split_fit[iz]
        )
        # inverse cumulative transformation to point
        sct.run(
            fsloutput
            + "flirt -in "
            + file_point_split[z_init]
            + " -ref "
            + file_point_split[z_init]
            + " -applyxfm -init "
            + file_mat_inv_cumul_fit[iz]
            + " -out "
            + file_point_split_fit[iz]
            + " -interp nearestneighbour"
        )

    # Merge into 4D volume
    print "\nMerge into 4D volume..."
    # im_anat_list = [Image(fname) for fname in glob.glob('tmp.anat_orient_fit_z*.nii')]
    fname_anat_list = glob.glob("tmp.anat_orient_fit_z*.nii")
    im_anat_concat = concat_data(fname_anat_list, 2)
    im_anat_concat.setFileName("tmp.anat_orient_fit.nii")
    im_anat_concat.save()

    # im_mask_list = [Image(fname) for fname in glob.glob('tmp.mask_orient_fit_z*.nii')]
    fname_mask_list = glob.glob("tmp.mask_orient_fit_z*.nii")
    im_mask_concat = concat_data(fname_mask_list, 2)
    im_mask_concat.setFileName("tmp.mask_orient_fit.nii")
    im_mask_concat.save()

    # im_point_list = [Image(fname) for fname in 	glob.glob('tmp.point_orient_fit_z*.nii')]
    fname_point_list = glob.glob("tmp.point_orient_fit_z*.nii")
    im_point_concat = concat_data(fname_point_list, 2)
    im_point_concat.setFileName("tmp.point_orient_fit.nii")
    im_point_concat.save()

    # Copy header geometry from input data
    print "\nCopy header geometry from input data..."
    im_anat = Image("tmp.anat_orient.nii")
    im_anat_orient_fit = Image("tmp.anat_orient_fit.nii")
    im_mask_orient_fit = Image("tmp.mask_orient_fit.nii")
    im_point_orient_fit = Image("tmp.point_orient_fit.nii")
    im_anat_orient_fit = copy_header(im_anat, im_anat_orient_fit)
    im_mask_orient_fit = copy_header(im_anat, im_mask_orient_fit)
    im_point_orient_fit = copy_header(im_anat, im_point_orient_fit)
    for im in [im_anat_orient_fit, im_mask_orient_fit, im_point_orient_fit]:
        im.save()

    # Reorient outputs into the initial orientation of the input image
    print "\nReorient the centerline into the initial orientation of the input image..."
    set_orientation("tmp.point_orient_fit.nii", input_image_orientation, "tmp.point_orient_fit.nii")
    set_orientation("tmp.mask_orient_fit.nii", input_image_orientation, "tmp.mask_orient_fit.nii")

    # Generate output file (in current folder)
    print "\nGenerate output file (in current folder)..."
    os.chdir("..")  # come back to parent folder
    fname_output_centerline = sct.generate_output_file(
        path_tmp + "/tmp.point_orient_fit.nii", file_anat + "_centerline" + ext_anat
    )

    # Delete temporary files
    if remove_tmp_files == 1:
        print "\nRemove temporary files..."
        sct.run("rm -rf " + path_tmp, error_exit="warning")

    # print number of warnings
    print "\nNumber of warnings: " + str(
        warning_count
    ) + " (if >10, you should probably reduce the gap and/or increase the kernel size"

    # display elapsed time
    elapsed_time = time() - start_time
    print "\nFinished! \n\tGenerated file: " + fname_output_centerline + "\n\tElapsed time: " + str(
        int(round(elapsed_time))
    ) + "s\n"
Exemplo n.º 34
0
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix, method, file_mask):
    """
    Compute DTI.
    :param fname_in: input 4d file.
    :param bvals: bvals txt file
    :param bvecs: bvecs txt file
    :param prefix: output prefix. Example: "dti_"
    :param method: algo for computing dti
    :return: True/False
    """
    # Open file.
    from msct_image import Image
    nii = Image(fname_in)
    data = nii.data
    sct.printv('data.shape (%d, %d, %d, %d)' % data.shape)

    # open bvecs/bvals
    from dipy.io import read_bvals_bvecs
    bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs)
    from dipy.core.gradients import gradient_table
    gtab = gradient_table(bvals, bvecs)

    # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image.
    if not file_mask == '':
        sct.printv('Open mask file...', param.verbose)
        # open mask file
        nii_mask = Image(file_mask)
        mask = nii_mask.data

    # fit tensor model
    sct.printv('Computing tensor using "' + method + '" method...',
               param.verbose)
    import dipy.reconst.dti as dti
    if method == 'standard':
        tenmodel = dti.TensorModel(gtab)
        if file_mask == '':
            tenfit = tenmodel.fit(data)
        else:
            tenfit = tenmodel.fit(data, mask)
    elif method == 'restore':
        import dipy.denoise.noise_estimate as ne
        sigma = ne.estimate_sigma(data)
        dti_restore = dti.TensorModel(gtab, fit_method='RESTORE', sigma=sigma)
        if file_mask == '':
            tenfit = dti_restore.fit(data)
        else:
            tenfit = dti_restore.fit(data, mask)

    # Compute metrics
    sct.printv('Computing metrics...', param.verbose)
    # FA
    from dipy.reconst.dti import fractional_anisotropy
    nii.data = fractional_anisotropy(tenfit.evals)
    nii.setFileName(prefix + 'FA.nii.gz')
    nii.save('float32')
    # MD
    from dipy.reconst.dti import mean_diffusivity
    nii.data = mean_diffusivity(tenfit.evals)
    nii.setFileName(prefix + 'MD.nii.gz')
    nii.save('float32')
    # RD
    from dipy.reconst.dti import radial_diffusivity
    nii.data = radial_diffusivity(tenfit.evals)
    nii.setFileName(prefix + 'RD.nii.gz')
    nii.save('float32')
    # AD
    from dipy.reconst.dti import axial_diffusivity
    nii.data = axial_diffusivity(tenfit.evals)
    nii.setFileName(prefix + 'AD.nii.gz')
    nii.save('float32')

    return True
Exemplo n.º 35
0
def main():
    # Initialization
    fname_data = ''
    suffix_out = '_crop'
    remove_temp_files = param.remove_temp_files
    verbose = param.verbose
    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; '  # for faster processing, all outputs are in NIFTI
    remove_temp_files = param.remove_temp_files

    # Parameters for debug mode
    if param.debug:
        print '\n*** WARNING: DEBUG MODE ON ***\n'
        fname_data = path_sct + '/testing/data/errsm_23/t2/t2.nii.gz'
        remove_temp_files = 0
    else:
        # Check input parameters
        try:
            opts, args = getopt.getopt(sys.argv[1:], 'hi:r:v:')
        except getopt.GetoptError:
            usage()
        if not opts:
            usage()
        for opt, arg in opts:
            if opt == '-h':
                usage()
            elif opt in ('-i'):
                fname_data = arg
            elif opt in ('-r'):
                remove_temp_files = int(arg)
            elif opt in ('-v'):
                verbose = int(arg)

    # display usage if a mandatory argument is not provided
    if fname_data == '':
        usage()

    # Check file existence
    sct.printv('\nCheck file existence...', verbose)
    sct.check_file_exist(fname_data, verbose)

    # Get dimensions of data
    sct.printv('\nGet dimensions of data...', verbose)
    nx, ny, nz, nt, px, py, pz, pt = Image(fname_data).dim
    sct.printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), verbose)
    # check if 4D data
    if not nt == 1:
        sct.printv(
            '\nERROR in ' + os.path.basename(__file__) +
            ': Data should be 3D.\n', 1, 'error')
        sys.exit(2)

    # print arguments
    print '\nCheck parameters:'
    print '  data ................... ' + fname_data
    print

    # Extract path/file/extension
    path_data, file_data, ext_data = sct.extract_fname(fname_data)
    path_out, file_out, ext_out = '', file_data + suffix_out, ext_data

    # create temporary folder
    path_tmp = 'tmp.' + time.strftime("%y%m%d%H%M%S") + '/'
    sct.run('mkdir ' + path_tmp)

    # copy files into tmp folder
    sct.run('isct_c3d ' + fname_data + ' -o ' + path_tmp + 'data.nii')

    # go to tmp folder
    os.chdir(path_tmp)

    # change orientation
    sct.printv('\nChange orientation to RPI...', verbose)
    set_orientation('data.nii', 'RPI', 'data_rpi.nii')

    # get image of medial slab
    sct.printv('\nGet image of medial slab...', verbose)
    image_array = nibabel.load('data_rpi.nii').get_data()
    nx, ny, nz = image_array.shape
    scipy.misc.imsave('image.jpg', image_array[math.floor(nx / 2), :, :])

    # Display the image
    sct.printv('\nDisplay image and get cropping region...', verbose)
    fig = plt.figure()
    # fig = plt.gcf()
    # ax = plt.gca()
    ax = fig.add_subplot(111)
    img = mpimg.imread("image.jpg")
    implot = ax.imshow(img.T)
    implot.set_cmap('gray')
    plt.gca().invert_yaxis()
    # mouse callback
    ax.set_title(
        'Left click on the top and bottom of your cropping field.\n Right click to remove last point.\n Close window when your done.'
    )
    line, = ax.plot([], [], 'ro')  # empty line
    cropping_coordinates = LineBuilder(line)
    plt.show()
    # disconnect callback
    # fig.canvas.mpl_disconnect(line)

    # check if user clicked two times
    if len(cropping_coordinates.xs) != 2:
        sct.printv('\nERROR: You have to select two points. Exit program.\n',
                   1, 'error')
        sys.exit(2)

    # convert coordinates to integer
    zcrop = [int(i) for i in cropping_coordinates.ys]

    # sort coordinates
    zcrop.sort()

    # crop image
    sct.printv('\nCrop image...', verbose)
    nii = Image('data_rpi.nii')
    data_crop = nii.data[:, :, zcrop[0]:zcrop[1]]
    nii.data = data_crop
    nii.setFileName('data_rpi_crop.nii')
    nii.save()

    # come back to parent folder
    os.chdir('..')

    sct.printv('\nGenerate output files...', verbose)
    sct.generate_output_file(path_tmp + 'data_rpi_crop.nii',
                             path_out + file_out + ext_out)

    # Remove temporary files
    if remove_temp_files == 1:
        print('\nRemove temporary files...')
        sct.run('rm -rf ' + path_tmp)

    # to view results
    print '\nDone! To view results, type:'
    print 'fslview ' + path_out + file_out + ext_out + ' &'
    print
def compute_csa(fname_segmentation, verbose, remove_temp_files, step, smoothing_param, figure_fit, file_csa_volume, slices, vert_levels, fname_vertebral_labeling='', algo_fitting = 'hanning', type_window = 'hanning', window_length = 80):

    # Extract path, file and extension
    fname_segmentation = os.path.abspath(fname_segmentation)
    path_data, file_data, ext_data = sct.extract_fname(fname_segmentation)

    # create temporary folder
    sct.printv('\nCreate temporary folder...', verbose)
    path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S") + '_'+str(randint(1, 1000000)), 1)
    sct.run('mkdir '+path_tmp, verbose)

    # Copying input data to tmp folder
    sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose)
    sct.run('sct_convert -i '+fname_segmentation+' -o '+path_tmp+'segmentation.nii.gz', verbose)
    # go to tmp folder
    os.chdir(path_tmp)
    # Change orientation of the input segmentation into RPI
    sct.printv('\nChange orientation to RPI...', verbose)
    sct.run('sct_image -i segmentation.nii.gz -setorient RPI -o segmentation_RPI.nii.gz', verbose)

    # Open segmentation volume
    sct.printv('\nOpen segmentation volume...', verbose)
    im_seg = Image('segmentation_RPI.nii.gz')
    data_seg = im_seg.data
    # hdr_seg = im_seg.hdr

    # Get size of data
    sct.printv('\nGet data dimensions...', verbose)
    nx, ny, nz, nt, px, py, pz, pt = im_seg.dim
    sct.printv('  ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), verbose)

    # # Extract min and max index in Z direction
    X, Y, Z = (data_seg > 0).nonzero()
    min_z_index, max_z_index = min(Z), max(Z)

    # extract centerline and smooth it
    x_centerline_fit, y_centerline_fit, z_centerline, x_centerline_deriv, y_centerline_deriv, z_centerline_deriv = smooth_centerline('segmentation_RPI.nii.gz', algo_fitting=algo_fitting, type_window=type_window, window_length=window_length, verbose=verbose)
    z_centerline_scaled = [x*pz for x in z_centerline]

    # Compute CSA
    sct.printv('\nCompute CSA...', verbose)

    # Empty arrays in which CSA for each z slice will be stored
    csa = np.zeros(max_z_index-min_z_index+1)

    for iz in xrange(min_z_index, max_z_index+1):

        # compute the vector normal to the plane
        normal = normalize(np.array([x_centerline_deriv[iz-min_z_index], y_centerline_deriv[iz-min_z_index], z_centerline_deriv[iz-min_z_index]]))

        # compute the angle between the normal vector of the plane and the vector z
        angle = np.arccos(np.dot(normal, [0, 0, 1]))

        # compute the number of voxels, assuming the segmentation is coded for partial volume effect between 0 and 1.
        number_voxels = np.sum(data_seg[:, :, iz])

        # compute CSA, by scaling with voxel size (in mm) and adjusting for oblique plane
        csa[iz-min_z_index] = number_voxels * px * py * np.cos(angle)

    sct.printv('\nSmooth CSA across slices...', verbose)
    if smoothing_param:
        from msct_smooth import smoothing_window
        sct.printv('.. Hanning window: '+str(smoothing_param)+' mm', verbose)
        csa_smooth = smoothing_window(csa, window_len=smoothing_param/pz, window='hanning', verbose=0)
        # display figure
        if verbose == 2:
            import matplotlib.pyplot as plt
            plt.figure()
            pltx, = plt.plot(z_centerline_scaled, csa, 'bo')
            pltx_fit, = plt.plot(z_centerline_scaled, csa_smooth, 'r', linewidth=2)
            plt.title("Cross-sectional area (CSA)")
            plt.xlabel('z (mm)')
            plt.ylabel('CSA (mm^2)')
            plt.legend([pltx, pltx_fit], ['Raw', 'Smoothed'])
            plt.show()
        # update variable
        csa = csa_smooth
    else:
        sct.printv('.. No smoothing!', verbose)


    # Create output text file
    sct.printv('\nWrite text file...', verbose)
    file_results = open('csa.txt', 'w')
    for i in range(min_z_index, max_z_index+1):
        file_results.write(str(int(i)) + ',' + str(csa[i-min_z_index])+'\n')
        # Display results
        sct.printv('z='+str(i-min_z_index)+': '+str(csa[i-min_z_index])+' mm^2', verbose, 'bold')
    file_results.close()

    # output volume of csa values
    sct.printv('\nCreate volume of CSA values...', verbose)
    data_csa = data_seg.astype(np.float32, copy=False)
    # loop across slices
    for iz in range(min_z_index, max_z_index+1):
        # retrieve seg pixels
        x_seg, y_seg = (data_csa[:, :, iz] > 0).nonzero()
        seg = [[x_seg[i],y_seg[i]] for i in range(0, len(x_seg))]
        # loop across pixels in segmentation
        for i in seg:
            # replace value with csa value
            data_csa[i[0], i[1], iz] = csa[iz-min_z_index]
    # replace data
    im_seg.data = data_csa
    # set original orientation
    # TODO: FIND ANOTHER WAY!!
    # im_seg.change_orientation(orientation) --> DOES NOT WORK!
    # set file name -- use .gz because faster to write
    im_seg.setFileName('csa_volume_RPI.nii.gz')
    im_seg.changeType('float32')
    # save volume
    im_seg.save()

    # get orientation of the input data
    im_seg_original = Image('segmentation.nii.gz')
    orientation = im_seg_original.orientation
    sct.run('sct_image -i csa_volume_RPI.nii.gz -setorient '+orientation+' -o '+file_csa_volume)

    # come back to parent folder
    os.chdir('..')

    # Generate output files
    sct.printv('\nGenerate output files...', verbose)
    copyfile(path_tmp+'csa.txt', path_data+param.fname_csa)
    # sct.generate_output_file(path_tmp+'csa.txt', path_data+param.fname_csa)  # extension already included in param.fname_csa
    sct.generate_output_file(path_tmp+file_csa_volume, path_data+file_csa_volume)  # extension already included in name_output

    # average csa across vertebral levels or slices if asked (flag -z or -l)
    if slices or vert_levels:
        from sct_extract_metric import save_metrics

        warning = ''
        if vert_levels and not fname_vertebral_labeling:
            sct.printv('\nERROR: Vertebral labeling file is missing. See usage.\n', 1, 'error')

        elif vert_levels and fname_vertebral_labeling:

            # from sct_extract_metric import get_slices_matching_with_vertebral_levels
            sct.printv('\tSelected vertebral levels... '+vert_levels)
            # convert the vertebral labeling file to RPI orientation
            im_vertebral_labeling = set_orientation(Image(fname_vertebral_labeling), 'RPI', fname_out=path_tmp+'vertebral_labeling_RPI.nii')

            # get the slices corresponding to the vertebral levels
            # slices, vert_levels_list, warning = get_slices_matching_with_vertebral_levels(data_seg, vert_levels, im_vertebral_labeling.data, 1)
            slices, vert_levels_list, warning = get_slices_matching_with_vertebral_levels_based_centerline(vert_levels, im_vertebral_labeling.data, x_centerline_fit, y_centerline_fit, z_centerline)

        elif not vert_levels:
            vert_levels_list = []

        sct.printv('Average CSA across slices...', type='info')

        # parse the selected slices
        slices_lim = slices.strip().split(':')
        slices_list = range(int(slices_lim[0]), int(slices_lim[1])+1)

        CSA_for_selected_slices = []
        # Read the file csa.txt and get the CSA for the selected slices
        with open(path_data+param.fname_csa) as openfile:
            for line in openfile:
                line_split = line.strip().split(',')
                if int(line_split[0]) in slices_list:
                    CSA_for_selected_slices.append(float(line_split[1]))

        # average the CSA
        mean_CSA = np.mean(np.asarray(CSA_for_selected_slices))
        std_CSA = np.std(np.asarray(CSA_for_selected_slices))

        sct.printv('Mean CSA: '+str(mean_CSA)+' +/- '+str(std_CSA)+' mm^2', type='info')

        # write result into output file
        save_metrics([0], [file_data], slices, [mean_CSA], [std_CSA], path_data + 'csa_mean.txt', path_data+file_csa_volume, 'nb_voxels x px x py x cos(theta) slice-by-slice (in mm^3)', '', actual_vert=vert_levels_list, warning_vert_levels=warning)

        # compute volume between the selected slices
        sct.printv('Compute the volume in between the selected slices...', type='info')
        nb_vox = np.sum(data_seg[:, :, slices_list])
        volume = nb_vox*px*py*pz
        sct.printv('Volume in between the selected slices: '+str(volume)+' mm^3', type='info')

        # write result into output file
        save_metrics([0], [file_data], slices, [volume], [np.nan], path_data + 'volume.txt', path_data+file_data, 'nb_voxels x px x py x pz (in mm^3)', '', actual_vert=vert_levels_list, warning_vert_levels=warning)

    # Remove temporary files
    if remove_temp_files:
        sct.printv('\nRemove temporary files...')
        sct.run('rm -rf '+path_tmp, error_exit='warning')
def extract_centerline(fname_segmentation, remove_temp_files, verbose = 0, algo_fitting = 'hanning', type_window = 'hanning', window_length = 80):

    # Extract path, file and extension
    fname_segmentation = os.path.abspath(fname_segmentation)
    path_data, file_data, ext_data = sct.extract_fname(fname_segmentation)

    # create temporary folder
    sct.printv('\nCreate temporary folder...', verbose)
    path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S") + '_'+str(randint(1, 1000000)), 1)
    sct.run('mkdir '+path_tmp, verbose)

    # Copying input data to tmp folder
    sct.printv('\nCopying data to tmp folder...', verbose)
    sct.run('sct_convert -i '+fname_segmentation+' -o '+path_tmp+'segmentation.nii.gz', verbose)

    # go to tmp folder
    os.chdir(path_tmp)

    # Change orientation of the input centerline into RPI
    sct.printv('\nOrient centerline to RPI orientation...', verbose)
    # fname_segmentation_orient = 'segmentation_RPI.nii.gz'
    # BELOW DOES NOT WORK (JULIEN, 2015-10-17)
    # im_seg = Image(file_data+ext_data)
    # set_orientation(im_seg, 'RPI')
    # im_seg.setFileName(fname_segmentation_orient)
    # im_seg.save()
    sct.run('sct_image -i segmentation.nii.gz -setorient RPI -o segmentation_RPI.nii.gz', verbose)

    # Open segmentation volume
    sct.printv('\nOpen segmentation volume...', verbose)
    im_seg = Image('segmentation_RPI.nii.gz')
    data = im_seg.data

    # Get size of data
    sct.printv('\nGet data dimensions...', verbose)
    nx, ny, nz, nt, px, py, pz, pt = im_seg.dim
    sct.printv('.. matrix size: '+str(nx)+' x '+str(ny)+' x '+str(nz), verbose)
    sct.printv('.. voxel size:  '+str(px)+'mm x '+str(py)+'mm x '+str(pz)+'mm', verbose)

    # # Get dimension
    # sct.printv('\nGet dimensions...', verbose)
    # nx, ny, nz, nt, px, py, pz, pt = im_seg.dim
    #
    # # Extract orientation of the input segmentation
    # orientation = get_orientation(im_seg)
    # sct.printv('\nOrientation of segmentation image: ' + orientation, verbose)
    #
    # sct.printv('\nOpen segmentation volume...', verbose)
    # data = im_seg.data
    # hdr = im_seg.hdr

    # Extract min and max index in Z direction
    X, Y, Z = (data>0).nonzero()
    min_z_index, max_z_index = min(Z), max(Z)
    x_centerline = [0 for i in range(0,max_z_index-min_z_index+1)]
    y_centerline = [0 for i in range(0,max_z_index-min_z_index+1)]
    z_centerline = [iz for iz in range(min_z_index, max_z_index+1)]
    # Extract segmentation points and average per slice
    for iz in range(min_z_index, max_z_index+1):
        x_seg, y_seg = (data[:,:,iz]>0).nonzero()
        x_centerline[iz-min_z_index] = np.mean(x_seg)
        y_centerline[iz-min_z_index] = np.mean(y_seg)
    for k in range(len(X)):
        data[X[k], Y[k], Z[k]] = 0

    # extract centerline and smooth it
    x_centerline_fit, y_centerline_fit, z_centerline_fit, x_centerline_deriv, y_centerline_deriv, z_centerline_deriv = smooth_centerline('segmentation_RPI.nii.gz', type_window = type_window, window_length = window_length, algo_fitting = algo_fitting, verbose = verbose)

    if verbose == 2:
            import matplotlib.pyplot as plt

            #Creation of a vector x that takes into account the distance between the labels
            nz_nonz = len(z_centerline)
            x_display = [0 for i in range(x_centerline_fit.shape[0])]
            y_display = [0 for i in range(y_centerline_fit.shape[0])]
            for i in range(0, nz_nonz, 1):
                x_display[int(z_centerline[i]-z_centerline[0])] = x_centerline[i]
                y_display[int(z_centerline[i]-z_centerline[0])] = y_centerline[i]

            plt.figure(1)
            plt.subplot(2,1,1)
            plt.plot(z_centerline_fit, x_display, 'ro')
            plt.plot(z_centerline_fit, x_centerline_fit)
            plt.xlabel("Z")
            plt.ylabel("X")
            plt.title("x and x_fit coordinates")

            plt.subplot(2,1,2)
            plt.plot(z_centerline_fit, y_display, 'ro')
            plt.plot(z_centerline_fit, y_centerline_fit)
            plt.xlabel("Z")
            plt.ylabel("Y")
            plt.title("y and y_fit coordinates")
            plt.show()


    # Create an image with the centerline
    for iz in range(min_z_index, max_z_index+1):
        data[round(x_centerline_fit[iz-min_z_index]), round(y_centerline_fit[iz-min_z_index]), iz] = 1 # if index is out of bounds here for hanning: either the segmentation has holes or labels have been added to the file
    # Write the centerline image in RPI orientation
    # hdr.set_data_dtype('uint8') # set imagetype to uint8
    sct.printv('\nWrite NIFTI volumes...', verbose)
    im_seg.data = data
    im_seg.setFileName('centerline_RPI.nii.gz')
    im_seg.changeType('uint8')
    im_seg.save()

    sct.printv('\nSet to original orientation...', verbose)
    # get orientation of the input data
    im_seg_original = Image('segmentation.nii.gz')
    orientation = im_seg_original.orientation
    sct.run('sct_image -i centerline_RPI.nii.gz -setorient '+orientation+' -o centerline.nii.gz')

    # create a txt file with the centerline
    name_output_txt = 'centerline.txt'
    sct.printv('\nWrite text file...', verbose)
    file_results = open(name_output_txt, 'w')
    for i in range(min_z_index, max_z_index+1):
        file_results.write(str(int(i)) + ' ' + str(x_centerline_fit[i-min_z_index]) + ' ' + str(y_centerline_fit[i-min_z_index]) + '\n')
    file_results.close()

    # come back to parent folder
    os.chdir('..')

    # Generate output files
    sct.printv('\nGenerate output files...', verbose)
    sct.generate_output_file(path_tmp+'centerline.nii.gz', file_data+'_centerline.nii.gz')
    sct.generate_output_file(path_tmp+'centerline.txt', file_data+'_centerline.txt')

    # Remove temporary files
    if remove_temp_files:
        sct.printv('\nRemove temporary files...', verbose)
        sct.run('rm -rf '+path_tmp, verbose)

    return file_data+'_centerline.nii.gz'
Exemplo n.º 38
0
zmin_cord = np.min(np.nonzero(zsum))
zmax_cord = np.max(np.nonzero(zsum))

# duplicate WM and GM atlas towards the top and bottom slices to match the cord template
# bottom slices
for iz in range(zmin_cord, zmin_wm):
    data_wm[:, :, iz] = data_wm[:, :, zmin_wm]
    data_gm[:, :, iz] = data_gm[:, :, zmin_wm]
# top slices
for iz in range(zmax_wm, zmax_cord):
    data_wm[:, :, iz] = data_wm[:, :, zmax_wm]
    data_gm[:, :, iz] = data_gm[:, :, zmax_wm]

# save modified atlases
im_wm.setFileName('wm_ext.nii.gz')
im_wm.data = data_wm
im_wm.save()
im_gm.setFileName('gm_ext.nii.gz')
im_gm.data = data_gm
im_gm.save()

# sum modified wm/gm
data_wmgm = data_wm + data_gm

# save wm/gm
im_wm.setFileName('wmgm_ext.nii.gz')
im_wm.data = data_wmgm
im_wm.save()

# register wmgm --> cord
sct.run('cp '+fname_cord+' cord.nii.gz')
Exemplo n.º 39
0
def main(args=None):

    dim_list = ['x', 'y', 'z', 't']

    if not args:
        args = sys.argv[1:]

    # Get parser info
    parser = get_parser()
    arguments = parser.parse(args)
    fname_in = arguments["-i"]
    fname_out = arguments["-o"]
    verbose = int(arguments['-v'])
    if '-type' in arguments:
        output_type = arguments['-type']
    else:
        output_type = ''

    # Open file(s)
    im = Image(fname_in)
    data = im.data  # 3d or 4d numpy array
    dim = im.dim

    # run command
    if '-otsu' in arguments:
        param = arguments['-otsu']
        data_out = otsu(data, param)

    elif '-otsu_adap' in arguments:
        param = arguments['-otsu_adap']
        data_out = otsu_adap(data, param[0], param[1])

    elif '-otsu_median' in arguments:
        param = arguments['-otsu_median']
        data_out = otsu_median(data, param[0], param[1])

    elif '-thr' in arguments:
        param = arguments['-thr']
        data_out = threshold(data, param)

    elif '-percent' in arguments:
        param = arguments['-percent']
        data_out = perc(data, param)

    elif '-bin' in arguments:
        bin_thr = arguments['-bin']
        data_out = binarise(data, bin_thr=bin_thr)

    elif '-add' in arguments:
        from numpy import sum
        data2 = get_data_or_scalar(arguments["-add"], data)
        data_concat = concatenate_along_4th_dimension(data, data2)
        data_out = sum(data_concat, axis=3)

    elif '-sub' in arguments:
        data2 = get_data_or_scalar(arguments['-sub'], data)
        data_out = data - data2

    elif "-laplacian" in arguments:
        sigmas = arguments["-laplacian"]
        if len(sigmas) == 1:
            sigmas = [sigmas for i in range(len(data.shape))]
        elif len(sigmas) != len(data.shape):
            printv(
                parser.usage.generate(
                    error=
                    'ERROR: -laplacian need the same number of inputs as the number of image dimension OR only one input'
                ))
        # adjust sigma based on voxel size
        sigmas = [sigmas[i] / dim[i + 4] for i in range(3)]
        # smooth data
        data_out = laplacian(data, sigmas)

    elif '-mul' in arguments:
        from numpy import prod
        data2 = get_data_or_scalar(arguments["-mul"], data)
        data_concat = concatenate_along_4th_dimension(data, data2)
        data_out = prod(data_concat, axis=3)

    elif '-div' in arguments:
        from numpy import divide
        data2 = get_data_or_scalar(arguments["-div"], data)
        data_out = divide(data, data2)

    elif '-mean' in arguments:
        from numpy import mean
        dim = dim_list.index(arguments['-mean'])
        if dim + 1 > len(
                np.shape(data)):  # in case input volume is 3d and dim=t
            data = data[..., np.newaxis]
        data_out = mean(data, dim)

    elif '-rms' in arguments:
        from numpy import mean, sqrt, square
        dim = dim_list.index(arguments['-rms'])
        if dim + 1 > len(
                np.shape(data)):  # in case input volume is 3d and dim=t
            data = data[..., np.newaxis]
        data_out = sqrt(mean(square(data.astype(float)), dim))

    elif '-std' in arguments:
        from numpy import std
        dim = dim_list.index(arguments['-std'])
        if dim + 1 > len(
                np.shape(data)):  # in case input volume is 3d and dim=t
            data = data[..., np.newaxis]
        data_out = std(data, dim, ddof=1)

    elif "-smooth" in arguments:
        sigmas = arguments["-smooth"]
        if len(sigmas) == 1:
            sigmas = [sigmas[0] for i in range(len(data.shape))]
        elif len(sigmas) != len(data.shape):
            printv(
                parser.usage.generate(
                    error=
                    'ERROR: -smooth need the same number of inputs as the number of image dimension OR only one input'
                ))
        # adjust sigma based on voxel size
        sigmas = [sigmas[i] / dim[i + 4] for i in range(3)]
        # smooth data
        data_out = smooth(data, sigmas)

    elif '-dilate' in arguments:
        data_out = dilate(data, arguments['-dilate'])

    elif '-erode' in arguments:
        data_out = erode(data, arguments['-erode'])

    elif '-denoise' in arguments:
        # parse denoising arguments
        p, b = 1, 5  # default arguments
        list_denoise = arguments['-denoise']
        for i in list_denoise:
            if 'p' in i:
                p = int(i.split('=')[1])
            if 'b' in i:
                b = int(i.split('=')[1])
        data_out = denoise_nlmeans(data, patch_radius=p, block_radius=b)

    elif '-symmetrize' in arguments:
        data_out = (data +
                    data[range(data.shape[0] - 1, -1, -1), :, :]) / float(2)

    elif '-mi' in arguments:
        # input 1 = from flag -i --> im
        # input 2 = from flag -mi
        im_2 = Image(arguments['-mi'])
        compute_similarity(im.data,
                           im_2.data,
                           fname_out,
                           metric='mi',
                           verbose=verbose)
        data_out = None

    elif '-minorm' in arguments:
        im_2 = Image(arguments['-minorm'])
        compute_similarity(im.data,
                           im_2.data,
                           fname_out,
                           metric='minorm',
                           verbose=verbose)
        data_out = None

    elif '-corr' in arguments:
        # input 1 = from flag -i --> im
        # input 2 = from flag -mi
        im_2 = Image(arguments['-corr'])
        compute_similarity(im.data,
                           im_2.data,
                           fname_out,
                           metric='corr',
                           verbose=verbose)
        data_out = None

    # if no flag is set
    else:
        data_out = None
        printv(
            parser.usage.generate(
                error=
                'ERROR: you need to specify an operation to do on the input image'
            ))

    if data_out is not None:
        # Write output
        nii_out = Image(fname_in)  # use header of input file
        nii_out.data = data_out
        nii_out.setFileName(fname_out)
        nii_out.save(type=output_type)
    # TODO: case of multiple outputs
    # assert len(data_out) == n_out
    # if n_in == n_out:
    #     for im_in, d_out, fn_out in zip(nii, data_out, fname_out):
    #         im_in.data = d_out
    #         im_in.setFileName(fn_out)
    #         if "-w" in arguments:
    #             im_in.hdr.set_intent('vector', (), '')
    #         im_in.save()
    # elif n_out == 1:
    #     nii[0].data = data_out[0]
    #     nii[0].setFileName(fname_out[0])
    #     if "-w" in arguments:
    #             nii[0].hdr.set_intent('vector', (), '')
    #     nii[0].save()
    # elif n_out > n_in:
    #     for dat_out, name_out in zip(data_out, fname_out):
    #         im_out = nii[0].copy()
    #         im_out.data = dat_out
    #         im_out.setFileName(name_out)
    #         if "-w" in arguments:
    #             im_out.hdr.set_intent('vector', (), '')
    #         im_out.save()
    # else:
    #     printv(parser.usage.generate(error='ERROR: not the correct numbers of inputs and outputs'))

    # display message
    if data_out is not None:
        sct.display_viewer_syntax([fname_out])
    else:
        printv('\nDone! File created: ' + fname_out, verbose, 'info')
Exemplo n.º 40
0
def register(src, dest, paramreg, param, i_step_str):

    # initiate default parameters of antsRegistration transformation
    ants_registration_params = {
        'rigid': '',
        'affine': '',
        'compositeaffine': '',
        'similarity': '',
        'translation': '',
        'bspline': ',10',
        'gaussiandisplacementfield': ',3,0',
        'bsplinedisplacementfield': ',5,10',
        'syn': ',3,0',
        'bsplinesyn': ',1,3'
    }

    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; '  # for faster processing, all outputs are in NIFTI'

    # set metricSize
    if paramreg.steps[i_step_str].metric == 'MI':
        metricSize = '32'  # corresponds to number of bins
    else:
        metricSize = '4'  # corresponds to radius (for CC, MeanSquares...)

    # set masking
    if param.fname_mask:
        fname_mask = 'mask.nii.gz'
        masking = '-x mask.nii.gz'
    else:
        fname_mask = ''
        masking = ''

    if paramreg.steps[i_step_str].algo == 'slicereg':
        from msct_image import find_zmin_zmax
        # threshold images (otherwise, automatic crop does not work -- see issue #293)
        src_th = sct.add_suffix(src, '_th')
        from msct_image import Image
        nii = Image(src)
        data = nii.data
        data[data < 0.1] = 0
        nii.data = data
        nii.setFileName(src_th)
        nii.save()
        # sct.run(fsloutput+'fslmaths '+src+' -thr 0.1 '+src_th, param.verbose)
        dest_th = sct.add_suffix(dest, '_th')
        nii = Image(dest)
        data = nii.data
        data[data < 0.1] = 0
        nii.data = data
        nii.setFileName(dest_th)
        nii.save()
        # sct.run(fsloutput+'fslmaths '+dest+' -thr 0.1 '+dest_th, param.verbose)
        # find zmin and zmax
        zmin_src, zmax_src = find_zmin_zmax(src_th)
        zmin_dest, zmax_dest = find_zmin_zmax(dest_th)
        zmin_total = max([zmin_src, zmin_dest])
        zmax_total = min([zmax_src, zmax_dest])
        # crop data
        src_crop = sct.add_suffix(src, '_crop')
        sct.run(
            'sct_crop_image -i ' + src + ' -o ' + src_crop +
            ' -dim 2 -start ' + str(zmin_total) + ' -end ' + str(zmax_total),
            param.verbose)
        dest_crop = sct.add_suffix(dest, '_crop')
        sct.run(
            'sct_crop_image -i ' + dest + ' -o ' + dest_crop +
            ' -dim 2 -start ' + str(zmin_total) + ' -end ' + str(zmax_total),
            param.verbose)
        # update variables
        src = src_crop
        dest = dest_crop
        # estimate transfo
        cmd = (
            'isct_antsSliceRegularizedRegistration '
            '-t Translation[0.5] '
            '-m ' + paramreg.steps[i_step_str].metric + '[' + dest + ',' +
            src + ',1,' + metricSize + ',Regular,0.2] '
            '-p ' + paramreg.steps[i_step_str].poly + ' '
            '-i ' + paramreg.steps[i_step_str].iter + ' '
            '-f 1 '
            '-s ' + paramreg.steps[i_step_str].smooth + ' '
            '-v 1 '  # verbose (verbose=2 does not exist, so we force it to 1)
            '-o [step' + i_step_str + ',' + src + '_regStep' + i_step_str +
            '.nii] '  # here the warp name is stage10 because antsSliceReg add "Warp"
            + masking)
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_pointwise':
        from msct_register import register_slicereg2d_pointwise
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_pointwise(
            src,
            dest,
            window_length=paramreg.steps[i_step_str].window_length,
            paramreg=Paramreg(step=paramreg.steps[i_step_str].step,
                              type=paramreg.steps[i_step_str].type,
                              algo='Translation',
                              metric=paramreg.steps[i_step_str].metric,
                              iter=paramreg.steps[i_step_str].iter,
                              shrink=paramreg.steps[i_step_str].shrink,
                              smooth=paramreg.steps[i_step_str].smooth,
                              gradStep=paramreg.steps[i_step_str].gradStep),
            warp_forward_out=warp_forward_out,
            warp_inverse_out=warp_inverse_out,
            factor=param.outlier_factor,
            verbose=param.verbose)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_translation':
        from msct_register import register_slicereg2d_translation
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_translation(
            src,
            dest,
            window_length=paramreg.steps[i_step_str].window_length,
            paramreg=Paramreg(step=paramreg.steps[i_step_str].step,
                              type=paramreg.steps[i_step_str].type,
                              algo='Translation',
                              metric=paramreg.steps[i_step_str].metric,
                              iter=paramreg.steps[i_step_str].iter,
                              shrink=paramreg.steps[i_step_str].shrink,
                              smooth=paramreg.steps[i_step_str].smooth,
                              gradStep=paramreg.steps[i_step_str].gradStep),
            fname_mask=fname_mask,
            warp_forward_out=warp_forward_out,
            warp_inverse_out=warp_inverse_out,
            factor=param.outlier_factor,
            remove_temp_files=param.remove_temp_files,
            verbose=param.verbose,
            ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_rigid':
        from msct_register import register_slicereg2d_rigid
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_rigid(
            src,
            dest,
            window_length=paramreg.steps[i_step_str].window_length,
            paramreg=Paramreg(step=paramreg.steps[i_step_str].step,
                              type=paramreg.steps[i_step_str].type,
                              algo='Rigid',
                              metric=paramreg.steps[i_step_str].metric,
                              iter=paramreg.steps[i_step_str].iter,
                              shrink=paramreg.steps[i_step_str].shrink,
                              smooth=paramreg.steps[i_step_str].smooth,
                              gradStep=paramreg.steps[i_step_str].gradStep),
            fname_mask=fname_mask,
            warp_forward_out=warp_forward_out,
            warp_inverse_out=warp_inverse_out,
            factor=param.outlier_factor,
            remove_temp_files=param.remove_temp_files,
            verbose=param.verbose,
            ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_affine':
        from msct_register import register_slicereg2d_affine
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_affine(
            src,
            dest,
            window_length=paramreg.steps[i_step_str].window_length,
            paramreg=Paramreg(step=paramreg.steps[i_step_str].step,
                              type=paramreg.steps[i_step_str].type,
                              algo='Affine',
                              metric=paramreg.steps[i_step_str].metric,
                              iter=paramreg.steps[i_step_str].iter,
                              shrink=paramreg.steps[i_step_str].shrink,
                              smooth=paramreg.steps[i_step_str].smooth,
                              gradStep=paramreg.steps[i_step_str].gradStep),
            fname_mask=fname_mask,
            warp_forward_out=warp_forward_out,
            warp_inverse_out=warp_inverse_out,
            factor=param.outlier_factor,
            remove_temp_files=param.remove_temp_files,
            verbose=param.verbose,
            ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_syn':
        from msct_register import register_slicereg2d_syn
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_syn(
            src,
            dest,
            window_length=paramreg.steps[i_step_str].window_length,
            paramreg=Paramreg(step=paramreg.steps[i_step_str].step,
                              type=paramreg.steps[i_step_str].type,
                              algo='SyN',
                              metric=paramreg.steps[i_step_str].metric,
                              iter=paramreg.steps[i_step_str].iter,
                              shrink=paramreg.steps[i_step_str].shrink,
                              smooth=paramreg.steps[i_step_str].smooth,
                              gradStep=paramreg.steps[i_step_str].gradStep),
            fname_mask=fname_mask,
            warp_forward_out=warp_forward_out,
            warp_inverse_out=warp_inverse_out,
            factor=param.outlier_factor,
            remove_temp_files=param.remove_temp_files,
            verbose=param.verbose,
            ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_bsplinesyn':
        from msct_register import register_slicereg2d_bsplinesyn
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_bsplinesyn(
            src,
            dest,
            window_length=paramreg.steps[i_step_str].window_length,
            paramreg=Paramreg(step=paramreg.steps[i_step_str].step,
                              type=paramreg.steps[i_step_str].type,
                              algo='BSplineSyN',
                              metric=paramreg.steps[i_step_str].metric,
                              iter=paramreg.steps[i_step_str].iter,
                              shrink=paramreg.steps[i_step_str].shrink,
                              smooth=paramreg.steps[i_step_str].smooth,
                              gradStep=paramreg.steps[i_step_str].gradStep),
            fname_mask=fname_mask,
            warp_forward_out=warp_forward_out,
            warp_inverse_out=warp_inverse_out,
            factor=param.outlier_factor,
            remove_temp_files=param.remove_temp_files,
            verbose=param.verbose,
            ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params:
        from msct_image import pad_image
        # Pad the destination image (because ants doesn't deform the extremities)
        # N.B. no need to pad if iter = 0
        if not paramreg.steps[i_step_str].iter == '0':
            dest_pad = sct.add_suffix(dest, '_pad')
            pad_image(dest, dest_pad, param.padding)
            dest = dest_pad

        cmd = (
            'isct_antsRegistration '
            '--dimensionality 3 '
            '--transform ' + paramreg.steps[i_step_str].algo + '[' +
            paramreg.steps[i_step_str].gradStep +
            ants_registration_params[paramreg.steps[i_step_str].algo.lower()] +
            '] '
            '--metric ' + paramreg.steps[i_step_str].metric + '[' + dest +
            ',' + src + ',1,' + metricSize + '] '
            '--convergence ' + paramreg.steps[i_step_str].iter + ' '
            '--shrink-factors ' + paramreg.steps[i_step_str].shrink + ' '
            '--smoothing-sigmas ' + paramreg.steps[i_step_str].smooth + 'mm '
            '--restrict-deformation 1x1x0 '
            '--output [step' + i_step_str + ',' + src + '_regStep' +
            i_step_str + '.nii] '
            '--interpolation BSpline[3] ' + masking)
        if param.verbose >= 1:
            cmd += ' --verbose 1'
        if paramreg.steps[i_step_str].algo in ['rigid', 'affine']:
            warp_forward_out = 'step' + i_step_str + '0GenericAffine.mat'
            warp_inverse_out = '-step' + i_step_str + '0GenericAffine.mat'
        else:
            warp_forward_out = 'step' + i_step_str + '0Warp.nii.gz'
            warp_inverse_out = 'step' + i_step_str + '0InverseWarp.nii.gz'
    else:
        sct.printv(
            '\nERROR: algo ' + paramreg.steps[i_step_str].algo +
            ' does not exist. Exit program\n', 1, 'error')

    # run registration
    status, output = sct.run(cmd, param.verbose)

    if os.path.isfile(warp_forward_out):
        # rename warping fields
        if paramreg.steps[i_step_str].algo in ['rigid', 'affine']:
            warp_forward = 'warp_forward_' + i_step_str + '.mat'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_' + i_step_str + '.mat'
        else:
            warp_forward = 'warp_forward_' + i_step_str + '.nii.gz'
            warp_inverse = 'warp_inverse_' + i_step_str + '.nii.gz'
            os.rename(warp_forward_out, warp_forward)
            os.rename(warp_inverse_out, warp_inverse)
    else:
        sct.printv(output, 1, 'error')
        sct.printv('\nERROR: ANTs failed. Exit program.\n', 1, 'error')

    return warp_forward, warp_inverse
Exemplo n.º 41
0
def main(args=None):

    # Initialization
    # fname_anat = ''
    # fname_centerline = ''
    sigma = 3  # default value of the standard deviation for the Gaussian smoothing (in terms of number of voxels)
    # remove_temp_files = param.remove_temp_files
    # verbose = param.verbose
    start_time = time.time()

    parser = get_parser()
    arguments = parser.parse(sys.argv[1:])

    fname_anat = arguments['-i']
    fname_centerline = arguments['-s']
    if '-smooth' in arguments:
        sigma = arguments['-smooth']
    if '-r' in arguments:
        remove_temp_files = int(arguments['-r'])
    if '-v' in arguments:
        verbose = int(arguments['-v'])

    # Display arguments
    sct.printv('\nCheck input arguments...')
    sct.printv('  Volume to smooth .................. ' + fname_anat)
    sct.printv('  Centerline ........................ ' + fname_centerline)
    sct.printv('  Sigma (mm) ........................ ' + str(sigma))
    sct.printv('  Verbose ........................... ' + str(verbose))

    # Check that input is 3D:
    from msct_image import Image
    nx, ny, nz, nt, px, py, pz, pt = Image(fname_anat).dim
    dim = 4  # by default, will be adjusted later
    if nt == 1:
        dim = 3
    if nz == 1:
        dim = 2
    if dim == 4:
        sct.printv(
            'WARNING: the input image is 4D, please split your image to 3D before smoothing spinalcord using :\n'
            'sct_image -i ' + fname_anat + ' -split t -o ' + fname_anat,
            verbose, 'warning')
        sct.printv('4D images not supported, aborting ...', verbose, 'error')

    # Extract path/file/extension
    path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat)
    path_centerline, file_centerline, ext_centerline = sct.extract_fname(
        fname_centerline)

    # create temporary folder
    sct.printv('\nCreate temporary folder...', verbose)
    path_tmp = sct.slash_at_the_end('tmp.' + time.strftime("%y%m%d%H%M%S"), 1)
    sct.run('mkdir ' + path_tmp, verbose)

    # Copying input data to tmp folder
    sct.printv('\nCopying input data to tmp folder and convert to nii...',
               verbose)
    sct.run('cp ' + fname_anat + ' ' + path_tmp + 'anat' + ext_anat, verbose)
    sct.run(
        'cp ' + fname_centerline + ' ' + path_tmp + 'centerline' +
        ext_centerline, verbose)

    # go to tmp folder
    os.chdir(path_tmp)

    # convert to nii format
    convert('anat' + ext_anat, 'anat.nii')
    convert('centerline' + ext_centerline, 'centerline.nii')

    # Change orientation of the input image into RPI
    sct.printv('\nOrient input volume to RPI orientation...')
    fname_anat_rpi = set_orientation('anat.nii', 'RPI', filename=True)
    move(fname_anat_rpi, 'anat_rpi.nii')
    # Change orientation of the input image into RPI
    sct.printv('\nOrient centerline to RPI orientation...')
    fname_centerline_rpi = set_orientation('centerline.nii',
                                           'RPI',
                                           filename=True)
    move(fname_centerline_rpi, 'centerline_rpi.nii')

    # Straighten the spinal cord
    # straighten segmentation
    sct.printv('\nStraighten the spinal cord using centerline/segmentation...',
               verbose)
    # check if warp_curve2straight and warp_straight2curve already exist (i.e. no need to do it another time)
    if os.path.isfile('../warp_curve2straight.nii.gz') and os.path.isfile(
            '../warp_straight2curve.nii.gz') and os.path.isfile(
                '../straight_ref.nii.gz'):
        # if they exist, copy them into current folder
        sct.printv(
            'WARNING: Straightening was already run previously. Copying warping fields...',
            verbose, 'warning')
        shutil.copy('../warp_curve2straight.nii.gz',
                    'warp_curve2straight.nii.gz')
        shutil.copy('../warp_straight2curve.nii.gz',
                    'warp_straight2curve.nii.gz')
        shutil.copy('../straight_ref.nii.gz', 'straight_ref.nii.gz')
        # apply straightening
        sct.run(
            'sct_apply_transfo -i anat_rpi.nii -w warp_curve2straight.nii.gz -d straight_ref.nii.gz -o anat_rpi_straight.nii -x spline',
            verbose)
    else:
        sct.run(
            'sct_straighten_spinalcord -i anat_rpi.nii -s centerline_rpi.nii -qc 0 -x spline',
            verbose)

    # Smooth the straightened image along z
    sct.printv('\nSmooth the straightened image along z...')
    sct.run(
        'sct_maths -i anat_rpi_straight.nii -smooth 0,0,' + str(sigma) +
        ' -o anat_rpi_straight_smooth.nii', verbose)

    # Apply the reversed warping field to get back the curved spinal cord
    sct.printv(
        '\nApply the reversed warping field to get back the curved spinal cord...'
    )
    sct.run(
        'sct_apply_transfo -i anat_rpi_straight_smooth.nii -o anat_rpi_straight_smooth_curved.nii -d anat.nii -w warp_straight2curve.nii.gz -x spline',
        verbose)

    # replace zeroed voxels by original image (issue #937)
    sct.printv('\nReplace zeroed voxels by original image...', verbose)
    nii_smooth = Image('anat_rpi_straight_smooth_curved.nii')
    data_smooth = nii_smooth.data
    data_input = Image('anat.nii').data
    indzero = np.where(data_smooth == 0)
    data_smooth[indzero] = data_input[indzero]
    nii_smooth.data = data_smooth
    nii_smooth.setFileName('anat_rpi_straight_smooth_curved_nonzero.nii')
    nii_smooth.save()

    # come back to parent folder
    os.chdir('..')

    # Generate output file
    sct.printv('\nGenerate output file...')
    sct.generate_output_file(
        path_tmp + '/anat_rpi_straight_smooth_curved_nonzero.nii',
        file_anat + '_smooth' + ext_anat)

    # Remove temporary files
    if remove_temp_files == 1:
        sct.printv('\nRemove temporary files...')
        sct.run('rm -rf ' + path_tmp)

    # Display elapsed time
    elapsed_time = time.time() - start_time
    sct.printv('\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) +
               's\n')

    # to view results
    sct.printv('Done! To view results, type:', verbose)
    sct.printv('fslview ' + file_anat + ' ' + file_anat + '_smooth &\n',
               verbose, 'info')
def register(src, dest, paramreg, param, i_step_str):

    # initiate default parameters of antsRegistration transformation
    ants_registration_params = {
        'rigid': '',
        'affine': '',
        'compositeaffine': '',
        'similarity': '',
        'translation': '',
        'bspline': ',10',
        'gaussiandisplacementfield': ',3,0',
        'bsplinedisplacementfield': ',5,10',
        'syn': ',3,0',
        'bsplinesyn': ',1,3'
    }
    output = ''  # default output if problem

    # display arguments
    sct.printv('Registration parameters:', param.verbose)
    sct.printv('  type ........... ' + paramreg.steps[i_step_str].type,
               param.verbose)
    sct.printv('  algo ........... ' + paramreg.steps[i_step_str].algo,
               param.verbose)
    sct.printv('  slicewise ...... ' + paramreg.steps[i_step_str].slicewise,
               param.verbose)
    sct.printv('  metric ......... ' + paramreg.steps[i_step_str].metric,
               param.verbose)
    sct.printv('  iter ........... ' + paramreg.steps[i_step_str].iter,
               param.verbose)
    sct.printv('  smooth ......... ' + paramreg.steps[i_step_str].smooth,
               param.verbose)
    sct.printv('  laplacian ...... ' + paramreg.steps[i_step_str].laplacian,
               param.verbose)
    sct.printv('  shrink ......... ' + paramreg.steps[i_step_str].shrink,
               param.verbose)
    sct.printv('  gradStep ....... ' + paramreg.steps[i_step_str].gradStep,
               param.verbose)
    sct.printv('  deformation .... ' + paramreg.steps[i_step_str].deformation,
               param.verbose)
    sct.printv('  init ........... ' + paramreg.steps[i_step_str].init,
               param.verbose)
    sct.printv('  poly ........... ' + paramreg.steps[i_step_str].poly,
               param.verbose)
    sct.printv('  dof ............ ' + paramreg.steps[i_step_str].dof,
               param.verbose)
    sct.printv('  smoothWarpXY ... ' + paramreg.steps[i_step_str].smoothWarpXY,
               param.verbose)

    # set metricSize
    if paramreg.steps[i_step_str].metric == 'MI':
        metricSize = '32'  # corresponds to number of bins
    else:
        metricSize = '4'  # corresponds to radius (for CC, MeanSquares...)

    # set masking
    if param.fname_mask:
        fname_mask = 'mask.nii.gz'
        masking = '-x mask.nii.gz'
    else:
        fname_mask = ''
        masking = ''

    if paramreg.steps[i_step_str].algo == 'slicereg':
        # check if user used type=label
        if paramreg.steps[i_step_str].type == 'label':
            sct.printv(
                '\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg',
                1, 'error')
        else:
            from msct_image import find_zmin_zmax
            # threshold images (otherwise, automatic crop does not work -- see issue #293)
            src_th = sct.add_suffix(src, '_th')
            from msct_image import Image
            nii = Image(src)
            data = nii.data
            data[data < 0.1] = 0
            nii.data = data
            nii.setFileName(src_th)
            nii.save()
            # sct.run(fsloutput+'fslmaths '+src+' -thr 0.1 '+src_th, param.verbose)
            dest_th = sct.add_suffix(dest, '_th')
            nii = Image(dest)
            data = nii.data
            data[data < 0.1] = 0
            nii.data = data
            nii.setFileName(dest_th)
            nii.save()
            # sct.run(fsloutput+'fslmaths '+dest+' -thr 0.1 '+dest_th, param.verbose)
            # find zmin and zmax
            zmin_src, zmax_src = find_zmin_zmax(src_th)
            zmin_dest, zmax_dest = find_zmin_zmax(dest_th)
            zmin_total = max([zmin_src, zmin_dest])
            zmax_total = min([zmax_src, zmax_dest])
            # crop data
            src_crop = sct.add_suffix(src, '_crop')
            sct.run(
                'sct_crop_image -i ' + src + ' -o ' + src_crop +
                ' -dim 2 -start ' + str(zmin_total) + ' -end ' +
                str(zmax_total), param.verbose)
            dest_crop = sct.add_suffix(dest, '_crop')
            sct.run(
                'sct_crop_image -i ' + dest + ' -o ' + dest_crop +
                ' -dim 2 -start ' + str(zmin_total) + ' -end ' +
                str(zmax_total), param.verbose)
            # update variables
            src = src_crop
            dest = dest_crop
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            # estimate transfo
            cmd = (
                'isct_antsSliceRegularizedRegistration '
                '-t Translation[' + paramreg.steps[i_step_str].gradStep + '] '
                '-m ' + paramreg.steps[i_step_str].metric + '[' + dest + ',' +
                src + ',1,' + metricSize + ',Regular,0.2] '
                '-p ' + paramreg.steps[i_step_str].poly + ' '
                '-i ' + paramreg.steps[i_step_str].iter + ' '
                '-f ' + paramreg.steps[i_step_str].shrink + ' '
                '-s ' + paramreg.steps[i_step_str].smooth + ' '
                '-v 1 '  # verbose (verbose=2 does not exist, so we force it to 1)
                '-o [step' + i_step_str + ',' + scr_regStep +
                '] '  # here the warp name is stage10 because antsSliceReg add "Warp"
                + masking)
            warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
            # run command
            status, output = sct.run(cmd, param.verbose)

    # ANTS 3d
    elif paramreg.steps[i_step_str].algo.lower(
    ) in ants_registration_params and paramreg.steps[
            i_step_str].slicewise == '0':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            # Pad the destination image (because ants doesn't deform the extremities)
            # N.B. no need to pad if iter = 0
            if not paramreg.steps[i_step_str].iter == '0':
                dest_pad = sct.add_suffix(dest, '_pad')
                sct.run('sct_image -i ' + dest + ' -o ' + dest_pad +
                        ' -pad 0,0,' + str(param.padding))
                dest = dest_pad
            # apply Laplacian filter
            if not paramreg.steps[i_step_str].laplacian == '0':
                sct.printv('\nApply Laplacian filter', param.verbose)
                sct.run('sct_maths -i ' + src + ' -laplacian ' +
                        paramreg.steps[i_step_str].laplacian + ',' +
                        paramreg.steps[i_step_str].laplacian + ',0 -o ' +
                        sct.add_suffix(src, '_laplacian'))
                sct.run('sct_maths -i ' + dest + ' -laplacian ' +
                        paramreg.steps[i_step_str].laplacian + ',' +
                        paramreg.steps[i_step_str].laplacian + ',0 -o ' +
                        sct.add_suffix(dest, '_laplacian'))
                src = sct.add_suffix(src, '_laplacian')
                dest = sct.add_suffix(dest, '_laplacian')
            # Estimate transformation
            sct.printv('\nEstimate transformation', param.verbose)
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            cmd = ('isct_antsRegistration '
                   '--dimensionality 3 '
                   '--transform ' + paramreg.steps[i_step_str].algo + '[' +
                   paramreg.steps[i_step_str].gradStep +
                   ants_registration_params[
                       paramreg.steps[i_step_str].algo.lower()] + '] '
                   '--metric ' + paramreg.steps[i_step_str].metric + '[' +
                   dest + ',' + src + ',1,' + metricSize + '] '
                   '--convergence ' + paramreg.steps[i_step_str].iter + ' '
                   '--shrink-factors ' + paramreg.steps[i_step_str].shrink +
                   ' '
                   '--smoothing-sigmas ' + paramreg.steps[i_step_str].smooth +
                   'mm '
                   '--restrict-deformation ' +
                   paramreg.steps[i_step_str].deformation + ' '
                   '--output [step' + i_step_str + ',' + scr_regStep + '] '
                   '--interpolation BSpline[3] '
                   '--verbose 1 ' + masking)
            # add init translation
            if not paramreg.steps[i_step_str].init == '':
                init_dict = {
                    'geometric': '0',
                    'centermass': '1',
                    'origin': '2'
                }
                cmd += ' -r [' + dest + ',' + src + ',' + init_dict[
                    paramreg.steps[i_step_str].init] + ']'
            # run command
            status, output = sct.run(cmd, param.verbose)
            # get appropriate file name for transformation
            if paramreg.steps[i_step_str].algo in [
                    'rigid', 'affine', 'translation'
            ]:
                warp_forward_out = 'step' + i_step_str + '0GenericAffine.mat'
                warp_inverse_out = '-step' + i_step_str + '0GenericAffine.mat'
            else:
                warp_forward_out = 'step' + i_step_str + '0Warp.nii.gz'
                warp_inverse_out = 'step' + i_step_str + '0InverseWarp.nii.gz'

    # ANTS 2d
    elif paramreg.steps[i_step_str].algo.lower(
    ) in ants_registration_params and paramreg.steps[
            i_step_str].slicewise == '1':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            from msct_register import register_slicewise
            # if shrink!=1, force it to be 1 (otherwise, it generates a wrong 3d warping field). TODO: fix that!
            if not paramreg.steps[i_step_str].shrink == '1':
                sct.printv(
                    '\nWARNING: when using slicewise with SyN or BSplineSyN, shrink factor needs to be one. Forcing shrink=1.',
                    1, 'warning')
                paramreg.steps[i_step_str].shrink = '1'
            warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
            register_slicewise(
                src,
                dest,
                paramreg=paramreg.steps[i_step_str],
                fname_mask=fname_mask,
                warp_forward_out=warp_forward_out,
                warp_inverse_out=warp_inverse_out,
                ants_registration_params=ants_registration_params,
                path_qc=param.path_qc,
                verbose=param.verbose)

    # slice-wise transfo
    elif paramreg.steps[i_step_str].algo in [
            'centermass', 'centermassrot', 'columnwise'
    ]:
        # if type=im, sends warning
        if paramreg.steps[i_step_str].type == 'im':
            sct.printv(
                '\nWARNING: algo ' + paramreg.steps[i_step_str].algo +
                ' should be used with type=seg.\n', 1, 'warning')
        # if type=label, exit with error
        elif paramreg.steps[i_step_str].type == 'label':
            sct.printv(
                '\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg',
                1, 'error')
        # check if user provided a mask-- if so, inform it will be ignored
        if not fname_mask == '':
            sct.printv(
                '\nWARNING: algo ' + paramreg.steps[i_step_str].algo +
                ' will ignore the provided mask.\n', 1, 'warning')
        # smooth data
        if not paramreg.steps[i_step_str].smooth == '0':
            sct.printv('\nSmooth data', param.verbose)
            sct.run('sct_maths -i ' + src + ' -smooth ' +
                    paramreg.steps[i_step_str].smooth + ',' +
                    paramreg.steps[i_step_str].smooth + ',0 -o ' +
                    sct.add_suffix(src, '_smooth'))
            sct.run('sct_maths -i ' + dest + ' -smooth ' +
                    paramreg.steps[i_step_str].smooth + ',' +
                    paramreg.steps[i_step_str].smooth + ',0 -o ' +
                    sct.add_suffix(dest, '_smooth'))
            src = sct.add_suffix(src, '_smooth')
            dest = sct.add_suffix(dest, '_smooth')
        from msct_register import register_slicewise
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        register_slicewise(src,
                           dest,
                           paramreg=paramreg.steps[i_step_str],
                           fname_mask=fname_mask,
                           warp_forward_out=warp_forward_out,
                           warp_inverse_out=warp_inverse_out,
                           ants_registration_params=ants_registration_params,
                           path_qc=param.path_qc,
                           verbose=param.verbose)

    else:
        sct.printv(
            '\nERROR: algo ' + paramreg.steps[i_step_str].algo +
            ' does not exist. Exit program\n', 1, 'error')

    # landmark-based registration
    if paramreg.steps[i_step_str].type in ['label']:
        # check if user specified ilabel and dlabel
        # TODO
        warp_forward_out = 'step' + i_step_str + '0GenericAffine.txt'
        warp_inverse_out = '-step' + i_step_str + '0GenericAffine.txt'
        from msct_register_landmarks import register_landmarks
        register_landmarks(src,
                           dest,
                           paramreg.steps[i_step_str].dof,
                           fname_affine=warp_forward_out,
                           verbose=param.verbose,
                           path_qc=param.path_qc)

    if not os.path.isfile(warp_forward_out):
        # no forward warping field for rigid and affine
        sct.printv(
            '\nERROR: file ' + warp_forward_out +
            ' doesn\'t exist (or is not a file).\n' + output +
            '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    elif not os.path.isfile(
            warp_inverse_out) and paramreg.steps[i_step_str].algo not in [
                'rigid', 'affine', 'translation'
            ] and paramreg.steps[i_step_str].type not in ['label']:
        # no inverse warping field for rigid and affine
        sct.printv(
            '\nERROR: file ' + warp_inverse_out +
            ' doesn\'t exist (or is not a file).\n' + output +
            '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    else:
        # rename warping fields
        if (paramreg.steps[i_step_str].algo.lower()
                in ['rigid', 'affine', 'translation']
                and paramreg.steps[i_step_str].slicewise == '0'):
            # if ANTs is used with affine/rigid --> outputs .mat file
            warp_forward = 'warp_forward_' + i_step_str + '.mat'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_' + i_step_str + '.mat'
        elif paramreg.steps[i_step_str].type in ['label']:
            # if label-based registration is used --> outputs .txt file
            warp_forward = 'warp_forward_' + i_step_str + '.txt'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_' + i_step_str + '.txt'
        else:
            warp_forward = 'warp_forward_' + i_step_str + '.nii.gz'
            warp_inverse = 'warp_inverse_' + i_step_str + '.nii.gz'
            os.rename(warp_forward_out, warp_forward)
            os.rename(warp_inverse_out, warp_inverse)

    return warp_forward, warp_inverse
#!/usr/bin/env python
# change type of template data

import os
import commands
import sys
from shutil import move
# Get path of the toolbox
status, path_sct = commands.getstatusoutput('echo $SCT_DIR')
# Append path that contains scripts, to be able to load modules
sys.path.append(path_sct + '/scripts')
from msct_image import Image
import sct_utils as sct

path_template = '/Users/julien/data/PAM50/template'
folder_PAM50 = 'PAM50/template/'
os.chdir(path_template)
sct.create_folder(folder_PAM50)

for file_template in ['MNI-Poly-AMU_T1.nii.gz', 'MNI-Poly-AMU_T2.nii.gz', 'MNI-Poly-AMU_T2star.nii.gz']:
    im = Image(file_template)
    # remove negative values
    data = im.data
    data[data<0] = 0
    im.data = data
    im.changeType('uint16')
    file_new = file_template.replace('MNI-Poly-AMU', 'PAM50')
    im.setFileName(file_new)
    im.save()
    # move to folder
    move(file_new, folder_PAM50+file_new)
Exemplo n.º 44
0
def wm_registration(param, smooth=False, init=False):
    path, fixed_name, ext = sct.extract_fname(param.fname_fixed)
    path_moving, moving_name, ext = sct.extract_fname(param.fname_moving)
    path, fixed_seg_name, ext = sct.extract_fname(param.fname_seg_fixed)
    path_moving_seg, moving_seg_name, ext = sct.extract_fname(param.fname_seg_moving)

    # cropping in x & y directions
    fixed_name_temp = fixed_name + "_crop"
    cmd = "sct_crop_image -i " + fixed_name + ext + " -o " + fixed_name_temp + ext + " -m " + fixed_seg_name + ext + " -shift 5,5 -dim 0,1"
    sct.run(cmd)
    fixed_name = fixed_name_temp

    fixed_seg_name_temp = fixed_seg_name+"_crop"
    sct.run("sct_crop_image -i " + fixed_seg_name + ext + " -o " + fixed_seg_name_temp + ext + " -m " + fixed_seg_name + ext + " -shift 5,5 -dim 0,1")
    fixed_seg_name = fixed_seg_name_temp

    # padding the images
    moving_name_pad = moving_name+"_pad"
    fixed_name_pad = fixed_name+"_pad"
    sct.run('sct_maths -i '+path_moving+moving_name+ext+' -o '+moving_name_pad+ext+' -pad 0,0,'+str(param.padding))
    sct.run('sct_maths -i '+fixed_name+ext+' -o '+fixed_name_pad+ext+' -pad 0,0,'+str(param.padding))
    moving_name = moving_name_pad
    fixed_name = fixed_name_pad

    moving_seg_name_pad = moving_seg_name+"_pad"
    sct.run('sct_maths -i '+path_moving_seg+moving_seg_name+ext+' -o '+moving_seg_name_pad+ext+' -pad 0,0,'+str(param.padding))
    moving_seg_name = moving_seg_name_pad

    fixed_seg_name_pad = fixed_seg_name+"_pad"
    sct.run('sct_maths -i '+fixed_seg_name+ext+' -o '+fixed_seg_name_pad+ext+' -pad 0,0,'+str(param.padding))
    fixed_seg_name = fixed_seg_name_pad

    if param.metric == 'MeanSquares':
        # offset
        old_min = 0
        old_max = 1
        new_min = 100
        new_max = 200

        fixed_im = Image(fixed_name+ext)
        fixed_im.data = (fixed_im.data - old_min)*(new_max - new_min)/(old_max - old_min) + new_min
        fixed_im.save()

        moving_im = Image(moving_name+ext)
        moving_im.data = (moving_im.data - old_min)*(new_max - new_min)/(old_max - old_min) + new_min
        moving_im.save()

    if smooth:
        # smoothing the images to register
        sct.printv('\nSmoothing the images...', verbose, 'normal')
        fixed_smooth = fixed_name+'_smooth'
        moving_smooth = moving_name+'_smooth'
        sct.run('sct_maths -i '+fixed_name+ext+' -smooth 1 -o '+fixed_smooth+ext)
        sct.run('sct_maths -i '+moving_name+ext+' -smooth 1 -o '+moving_smooth+ext)
        fixed_name = fixed_smooth
        moving_name = moving_smooth

    # registration of the gray matter
    sct.printv('\nDeforming the image...', verbose, 'normal')
    moving_name_reg = moving_name+"_deformed"

    param_multimodal_reg = 'step=1,type=seg,algo=slicereg,metric=MeanSquares:step=2,type=im,algo=bsplinesyn,metric=MeanSquares,iter=5,shrink=2'
    if param.transformation == 'BSplineSyN':
        transfo_params = ',3,0'
    elif param.transformation == 'SyN':     # SyN gives bad results...
        transfo_params = ',1,1'
    else:
        transfo_params = ''

    cmd = 'sct_register_multimodal -i '+moving_name+ext+' -d '+fixed_name+ext+' -iseg '+moving_seg_name+ext+' -dseg '+fixed_seg_name+ext+' -p '+param_multimodal_reg+' -o '+moving_name_reg
    ext_multimodal = '.nii'
    '''
    cmd = 'isct_antsRegistration --dimensionality 3 --interpolation '+param.interpolation+' --transform '+param.transformation+'['+param.gradient_step+transfo_params+'] --metric '+param.metric+'['+fixed_name+ext+','+moving_name+ext+',1,4] --output ['+moving_name_reg+','+moving_name_reg+ext+']  --convergence '+param.iteration+' --shrink-factors 1x1 --smoothing-sigmas 0x0 '
    if init:
        # initialize the transformation using the intensity
        cmd += ' -r ['+fixed_name+ext+','+moving_name+ext+',1] '

    cmd += " --masks ["+fixed_seg_name+ext+","+moving_seg_name + ext + "]"
    # cmd += " -m ["+fixed_seg_name+".nii,"+moving_seg_name+".nii]"
    '''
    sct.run(cmd)

    if init:
        # transform the .mat warping field into a nifti file:
        warp0_mat = moving_name_reg+'0GenericAffine.mat'
        warp0, warp0_inv = transform_mat_to_warp(warp0_mat, moving_name_reg+ext, fixed_name+ext)
        if param.transformation == 'Affine':
            warp_tot = warp0
            inverse_warp_tot = warp0_inv
        else:
            warp1 = moving_name_reg+'1Warp.nii.gz'
            warp1_inv = moving_name_reg+'1InverseWarp.nii.gz'

            # Concatenate the warping fields from the 2 steps into a warp total and an inverse
            warp_tot = moving_name_reg+'_warp_tot'+ext
            inverse_warp_tot = moving_name_reg+'_inverse_warp_tot'+ext

            sct.run('sct_concat_transfo -w '+warp0+','+warp1+' -d '+fixed_name+ext+' -o '+warp_tot)
            sct.run('sct_concat_transfo -w '+warp1_inv+','+warp0_inv+' -d '+moving_name+ext+' -o '+inverse_warp_tot)
    else:
        warp_tot = moving_name_reg+'0Warp.nii.gz'
        inverse_warp_tot = moving_name_reg+'0InverseWarp.nii.gz'


    if param.metric == 'MeanSquares':
        # removing offset
        fixed_im = Image(fixed_name+ext)
        fixed_im.data = (fixed_im.data - new_min)*(old_max - old_min)/(new_max - new_min) + old_min
        fixed_im.save()

        moving_im = Image(moving_name_reg+ext_multimodal)
        moving_im.data = (moving_im.data - new_min)*(old_max - old_min)/(new_max - new_min) + old_min
        moving_im.save()


    # un-padding the images
    moving_name_unpad = moving_name_reg+"_unpadded"
    fixed_name_unpad = fixed_name+"_unpadded"
    sct.run("sct_crop_image -i "+moving_name_reg+ext+" -dim 2 -start "+str(int(param.padding))+" -end -"+param.padding+" -o "+moving_name_unpad+ext)
    sct.run("sct_crop_image -i "+fixed_name+ext+" -dim 2 -start "+str(int(param.padding))+" -end -"+param.padding+" -o "+fixed_name_unpad+ext)

    '''
    # warp_tot = moving_name_reg+"0Warp.nii.gz"
    # inverse_warp_tot = moving_name_reg+"0InverseWarp.nii.gz"
    warp_unpad = sct.add_suffix(warp_tot, '_unpad')  # moving_name_reg+"0Warp_unpad.nii.gz"
    inverse_warp_unpad =  sct.add_suffix(inverse_warp_tot, '_unpad')  # moving_name_reg+"0InverseWarp_unpad.nii.gz"
    sct.run("sct_crop_image -i "+warp_tot+" -dim 2 -start "+str(int(param.padding))+" -end -"+param.padding+" -o "+warp_unpad)
    sct.run("sct_crop_image -i "+inverse_warp_tot+" -dim 2 -start "+str(int(param.padding))+" -end -"+param.padding+" -o "+inverse_warp_unpad)
    '''


    path_output, file_output, ext_output = sct.extract_fname(param.fname_output)
    warp_output = file_output+"_Warp"+ext_output
    inverse_warp_output = file_output+"_InverseWarp"+ext_output


    # with multimodal_reg
    sct.run("mv warp_"+moving_name+"2"+fixed_name+".nii.gz "+warp_output)
    sct.run("mv warp_"+fixed_name+"2"+moving_name+".nii.gz "+inverse_warp_output)
    '''
    # with antsReg
    sct.run("mv "+warp_unpad+" "+warp_output)
    sct.run("mv "+inverse_warp_unpad+" "+inverse_warp_output)
    '''

    moving_name_out = file_output+ext_output
    # put the result and the reference in the same space using a registration with ANTs with no iteration:
    sct.run('isct_antsRegistration -d 3 -t Translation[0] -m MI['+fixed_name_unpad+ext+','+moving_name_unpad+ext+',1,16] -o [regAffine,'+moving_name_out+'] -n BSpline[3] -c 0 -f 1 -s 0')

    return warp_output, inverse_warp_output
Exemplo n.º 45
0
def dmri_moco(param):

    file_data = 'dmri'
    ext_data = '.nii'
    file_b0 = 'b0'
    file_dwi = 'dwi'
    mat_final = 'mat_final/'
    file_dwi_group = 'dwi_averaged_groups'  # no extension
    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; '  # for faster processing, all outputs are in NIFTI
    ext_mat = 'Warp.nii.gz'  # warping field

    # Get dimensions of data
    sct.printv('\nGet dimensions of data...', param.verbose)
    nx, ny, nz, nt, px, py, pz, pt = Image(file_data + '.nii').dim
    sct.printv('  ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz),
               param.verbose)

    # Identify b=0 and DWI images
    sct.printv('\nIdentify b=0 and DWI images...', param.verbose)
    index_b0, index_dwi, nb_b0, nb_dwi = identify_b0('bvecs.txt',
                                                     param.fname_bvals,
                                                     param.bval_min,
                                                     param.verbose)

    # check if dmri and bvecs are the same size
    if not nb_b0 + nb_dwi == nt:
        sct.printv(
            '\nERROR in ' + os.path.basename(__file__) + ': Size of data (' +
            str(nt) + ') and size of bvecs (' + str(nb_b0 + nb_dwi) +
            ') are not the same. Check your bvecs file.\n', 1, 'error')
        sys.exit(2)

    # Prepare NIFTI (mean/groups...)
    #===================================================================================================================
    # Split into T dimension
    sct.printv('\nSplit along T dimension...', param.verbose)
    status, output = sct.run(
        'sct_split_data -i ' + file_data + ext_data + ' -dim t -suffix _T',
        param.verbose)

    # Merge b=0 images
    sct.printv('\nMerge b=0...', param.verbose)
    # cmd = fsloutput + 'fslmerge -t ' + file_b0
    # for it in range(nb_b0):
    #     cmd = cmd + ' ' + file_data + '_T' + str(index_b0[it]).zfill(4)
    cmd = 'sct_concat_data -dim t -o ' + file_b0 + ext_data + ' -i '
    for it in range(nb_b0):
        cmd = cmd + file_data + '_T' + str(
            index_b0[it]).zfill(4) + ext_data + ','
    cmd = cmd[:-1]  # remove ',' at the end of the string
    status, output = sct.run(cmd, param.verbose)
    sct.printv(('  File created: ' + file_b0), param.verbose)

    # Average b=0 images
    sct.printv('\nAverage b=0...', param.verbose)
    file_b0_mean = file_b0 + '_mean'
    sct.run(
        'sct_maths -i ' + file_b0 + '.nii' + ' -o ' + file_b0_mean + '.nii' +
        ' -mean t', param.verbose)
    # if not average_data_across_dimension(file_b0+'.nii', file_b0_mean+'.nii', 3):
    #     sct.printv('ERROR in average_data_across_dimension', 1, 'error')
    # cmd = fsloutput + 'fslmaths ' + file_b0 + ' -Tmean ' + file_b0_mean
    # status, output = sct.run(cmd, param.verbose)

    # Number of DWI groups
    nb_groups = int(math.floor(nb_dwi / param.group_size))

    # Generate groups indexes
    group_indexes = []
    for iGroup in range(nb_groups):
        group_indexes.append(index_dwi[(iGroup *
                                        param.group_size):((iGroup + 1) *
                                                           param.group_size)])

    # add the remaining images to the last DWI group
    nb_remaining = nb_dwi % param.group_size  # number of remaining images
    if nb_remaining > 0:
        nb_groups += 1
        group_indexes.append(index_dwi[len(index_dwi) -
                                       nb_remaining:len(index_dwi)])

    # DWI groups
    for iGroup in range(nb_groups):
        sct.printv('\nDWI group: ' + str((iGroup + 1)) + '/' + str(nb_groups),
                   param.verbose)

        # get index
        index_dwi_i = group_indexes[iGroup]
        nb_dwi_i = len(index_dwi_i)

        # Merge DW Images
        sct.printv('Merge DW images...', param.verbose)
        file_dwi_merge_i = file_dwi + '_' + str(iGroup)
        cmd = 'sct_concat_data -dim t -o ' + file_dwi_merge_i + ext_data + ' -i '
        for it in range(nb_dwi_i):
            cmd = cmd + file_data + '_T' + str(
                index_dwi_i[it]).zfill(4) + ext_data + ','
        cmd = cmd[:-1]  # remove ',' at the end of the string
        sct.run(cmd, param.verbose)
        # cmd = fsloutput + 'fslmerge -t ' + file_dwi_merge_i
        # for it in range(nb_dwi_i):
        #     cmd = cmd +' ' + file_data + '_T' + str(index_dwi_i[it]).zfill(4)

        # Average DW Images
        sct.printv('Average DW images...', param.verbose)
        file_dwi_mean = file_dwi + '_mean_' + str(iGroup)
        sct.run(
            'sct_maths -i ' + file_dwi_merge_i + '.nii' + ' -o ' +
            file_dwi_mean + '.nii' + ' -mean t', param.verbose)
        # if not average_data_across_dimension(file_dwi_merge_i+'.nii', file_dwi_mean+'.nii', 3):
        #     sct.printv('ERROR in average_data_across_dimension', 1, 'error')
        # cmd = fsloutput + 'fslmaths ' + file_dwi_merge_i + ' -Tmean ' + file_dwi_mean
        # sct.run(cmd, param.verbose)

    # Merge DWI groups means
    sct.printv('\nMerging DW files...', param.verbose)
    # file_dwi_groups_means_merge = 'dwi_averaged_groups'
    cmd = 'sct_concat_data -dim t -o ' + file_dwi_group + ext_data + ' -i '
    for iGroup in range(nb_groups):
        cmd = cmd + file_dwi + '_mean_' + str(iGroup) + ext_data + ','
    cmd = cmd[:-1]  # remove ',' at the end of the string
    sct.run(cmd, param.verbose)
    # cmd = fsloutput + 'fslmerge -t ' + file_dwi_group
    # for iGroup in range(nb_groups):
    #     cmd = cmd + ' ' + file_dwi + '_mean_' + str(iGroup)

    # Average DW Images
    # TODO: USEFULL ???
    sct.printv('\nAveraging all DW images...', param.verbose)
    fname_dwi_mean = 'dwi_mean'
    sct.run(
        'sct_maths -i ' + file_dwi_group + '.nii' + ' -o ' + file_dwi_group +
        '_mean.nii' + ' -mean t', param.verbose)
    # if not average_data_across_dimension(file_dwi_group+'.nii', file_dwi_group+'_mean.nii', 3):
    #     sct.printv('ERROR in average_data_across_dimension', 1, 'error')
    # sct.run(fsloutput + 'fslmaths ' + file_dwi_group + ' -Tmean ' + file_dwi_group+'_mean', param.verbose)

    # segment dwi images using otsu algorithm
    if param.otsu:
        sct.printv('\nSegment group DWI using OTSU algorithm...',
                   param.verbose)
        # import module
        otsu = importlib.import_module('sct_otsu')
        # get class from module
        param_otsu = otsu.param()  #getattr(otsu, param)
        param_otsu.fname_data = file_dwi_group + '.nii'
        param_otsu.threshold = param.otsu
        param_otsu.file_suffix = '_seg'
        # run otsu
        otsu.otsu(param_otsu)
        file_dwi_group = file_dwi_group + '_seg'

    # extract first DWI volume as target for registration
    nii = Image(file_dwi_group + '.nii')
    data_crop = nii.data[:, :, :, index_dwi[0]:index_dwi[0] + 1]
    nii.data = data_crop
    nii.setFileName('target_dwi.nii')
    nii.save()

    # START MOCO
    #===================================================================================================================

    # Estimate moco on b0 groups
    sct.printv(
        '\n-------------------------------------------------------------------------------',
        param.verbose)
    sct.printv('  Estimating motion on b=0 images...', param.verbose)
    sct.printv(
        '-------------------------------------------------------------------------------',
        param.verbose)
    param_moco = param
    param_moco.file_data = 'b0'
    if index_dwi[0] != 0:
        # If first DWI is not the first volume (most common), then there is a least one b=0 image before. In that case
        # select it as the target image for registration of all b=0
        param_moco.file_target = file_data + '_T' + str(
            index_b0[index_dwi[0] - 1]).zfill(4)
    else:
        # If first DWI is the first volume, then the target b=0 is the first b=0 from the index_b0.
        param_moco.file_target = file_data + '_T' + str(index_b0[0]).zfill(4)
    param_moco.path_out = ''
    param_moco.todo = 'estimate'
    param_moco.mat_moco = 'mat_b0groups'
    moco.moco(param_moco)

    # Estimate moco on dwi groups
    sct.printv(
        '\n-------------------------------------------------------------------------------',
        param.verbose)
    sct.printv('  Estimating motion on DW images...', param.verbose)
    sct.printv(
        '-------------------------------------------------------------------------------',
        param.verbose)
    param_moco.file_data = file_dwi_group
    param_moco.file_target = 'target_dwi'  # target is the first DW image (closest to the first b=0)
    param_moco.path_out = ''
    #param_moco.todo = 'estimate'
    param_moco.todo = 'estimate_and_apply'
    param_moco.mat_moco = 'mat_dwigroups'
    moco.moco(param_moco)

    # create final mat folder
    sct.create_folder(mat_final)

    # Copy b=0 registration matrices
    sct.printv('\nCopy b=0 registration matrices...', param.verbose)

    for it in range(nb_b0):
        sct.run(
            'cp ' + 'mat_b0groups/' + 'mat.T' + str(it) + ext_mat + ' ' +
            mat_final + 'mat.T' + str(index_b0[it]) + ext_mat, param.verbose)

    # Copy DWI registration matrices
    sct.printv('\nCopy DWI registration matrices...', param.verbose)
    for iGroup in range(nb_groups):
        for dwi in range(len(group_indexes[iGroup])):
            sct.run(
                'cp ' + 'mat_dwigroups/' + 'mat.T' + str(iGroup) + ext_mat +
                ' ' + mat_final + 'mat.T' + str(group_indexes[iGroup][dwi]) +
                ext_mat, param.verbose)

    # Spline Regularization along T
    if param.spline_fitting:
        moco.spline(mat_final, nt, nz, param.verbose, np.array(index_b0),
                    param.plot_graph)

    # combine Eddy Matrices
    if param.run_eddy:
        param.mat_2_combine = 'mat_eddy'
        param.mat_final = mat_final
        moco.combine_matrix(param)

    # Apply moco on all dmri data
    sct.printv(
        '\n-------------------------------------------------------------------------------',
        param.verbose)
    sct.printv('  Apply moco', param.verbose)
    sct.printv(
        '-------------------------------------------------------------------------------',
        param.verbose)
    param_moco.file_data = 'dmri'
    param_moco.file_target = file_dwi + '_mean_' + str(
        0)  # reference for reslicing into proper coordinate system
    param_moco.path_out = ''
    param_moco.mat_moco = mat_final
    param_moco.todo = 'apply'
    moco.moco(param_moco)

    # copy geometric information from header
    # NB: this is required because WarpImageMultiTransform in 2D mode wrongly sets pixdim(3) to "1".
    copy_header('dmri.nii', 'dmri_moco.nii')

    # generate b0_moco_mean and dwi_moco_mean
    cmd = 'sct_dmri_separate_b0_and_dwi -i dmri' + param.suffix + '.nii -b bvecs.txt -a 1'
    if not param.fname_bvals == '':
        cmd = cmd + ' -m ' + param.fname_bvals
    sct.run(cmd, param.verbose)
def wm_registration(param):
    path, fixed_name, ext = sct.extract_fname(param.fname_fixed)
    path_moving, moving_name, ext = sct.extract_fname(param.fname_moving)
    path, fixed_seg_name, ext = sct.extract_fname(param.fname_seg_fixed)
    path_moving_seg, moving_seg_name, ext = sct.extract_fname(param.fname_seg_moving)


    # cropping in x & y directions
    fixed_name_temp = fixed_name + "_crop"
    cmd = "sct_crop_image -i " + fixed_name + ext + " -o " + fixed_name_temp + ext + " -m " + fixed_seg_name + ext + " -shift 10,10 -dim 0,1"
    sct.run(cmd)
    fixed_name = fixed_name_temp

    fixed_seg_name_temp = fixed_name+"_crop"
    sct.run("sct_crop_image -i " + fixed_seg_name + ext + " -o " + fixed_seg_name_temp + ext + " -m " + fixed_seg_name + ext + " -shift 10,10 -dim 0,1")
    fixed_seg_name = fixed_seg_name_temp

    # padding the images
    moving_name_pad = moving_name+"_pad"
    fixed_name_pad = fixed_name+"_pad"
    sct.run("c3d "+path_moving+moving_name+ext+" -pad 0x0x"+param.padding+"vox 0x0x"+param.padding+"vox 0 -o "+moving_name_pad+ext)
    sct.run("c3d "+fixed_name+ext+" -pad 0x0x"+param.padding+"vox 0x0x"+param.padding+"vox 0 -o "+fixed_name_pad+ext)
    moving_name = moving_name_pad
    fixed_name = fixed_name_pad

    moving_seg_name_pad = moving_seg_name+"_pad"
    sct.run("c3d "+path_moving_seg+moving_seg_name+ext+" -pad 0x0x"+param.padding+"vox 0x0x"+param.padding+"vox 0 -o "+moving_seg_name_pad+ext)
    moving_seg_name = moving_seg_name_pad
    fixed_seg_name_pad = fixed_seg_name+"_pad"
    sct.run("c3d "+fixed_seg_name+ext+" -pad 0x0x"+param.padding+"vox 0x0x"+param.padding+"vox 0 -o "+fixed_seg_name_pad+ext)
    fixed_seg_name = fixed_seg_name_pad

    # offset
    old_min = 0
    old_max = 1
    new_min = 100
    new_max = 200

    fixed_im = Image(fixed_name+ext)
    fixed_im.data = (fixed_im.data - old_min)*(new_max - new_min)/(old_max - old_min) + new_min
    fixed_im.save()

    moving_im = Image(moving_name+ext)
    moving_im.data = (moving_im.data - old_min)*(new_max - new_min)/(old_max - old_min) + new_min
    moving_im.save()

    # registration of the gray matter
    sct.printv('\nDeforming the image...', reg_param.verbose, 'normal')
    moving_name_reg = moving_name+"_deformed"

    if param.transformation == 'BSplineSyN':
        transfo_params = ',3,0'
    elif param.transforlation == 'SyN':     # SyN gives bad results...
        transfo_params = ',1,1'
    else:
        transfo_params = ''

    cmd = 'isct_antsRegistration --dimensionality 3 --interpolation '+param.interpolation+' --transform '+param.transformation+'['+param.gradient_step+transfo_params+'] --metric '+param.metric+'['+fixed_name+ext+','+moving_name+ext+',1,4] --output ['+moving_name_reg+','+moving_name_reg+ext+']  --convergence '+param.iteration+' --shrink-factors 2x1 --smoothing-sigmas 0x0 '

    cmd += " --masks ["+fixed_seg_name+ext+","+moving_seg_name + ext + "]"
    # cmd += " -m ["+fixed_seg_name+".nii,"+moving_seg_name+".nii]"
    sct.run(cmd)
    moving_name = moving_name_reg

    # removing offset
    fixed_im = Image(fixed_name+ext)
    fixed_im.data = (fixed_im.data - new_min)*(old_max - old_min)/(new_max - new_min) + old_min
    fixed_im.save()

    moving_im = Image(moving_name+ext)
    moving_im.data = (moving_im.data - new_min)*(old_max - old_min)/(new_max - new_min) + old_min
    moving_im.save()

    # un-padding the images
    moving_name_unpad = moving_name+"_unpadded"
    sct.run("sct_crop_image -i "+moving_name+ext+" -dim 2 -start "+str(int(param.padding)-1)+" -end -"+param.padding+" -o "+moving_name_unpad+ext)

    path_output, file_output, ext_output = sct.extract_fname(param.fname_output)
    warp_output = file_output+"0Warp"+ext_output
    inverse_warp_output = file_output+"0InverseWarp"+ext_output
    sct.run("mv "+moving_name+"0Warp.nii.gz "+warp_output)
    sct.run("mv "+moving_name+"0InverseWarp.nii.gz "+inverse_warp_output)
    moving_name = moving_name_unpad

    moving_name_out = file_output+ext_output
    sct.run("c3d "+fixed_name+ext+" "+moving_name+ext+" -reslice-identity -o "+moving_name_out+ext)

    return warp_output, inverse_warp_output
Exemplo n.º 47
0
def create_mask():
    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; '  # for faster processing, all outputs are in NIFTI

    # parse argument for method
    method_type = param.process[0]
    # check method val
    if not method_type == 'center':
        method_val = param.process[1]

    # check existence of input files
    if method_type == 'centerline':
        sct.check_file_exist(method_val, param.verbose)

    # Extract path/file/extension
    path_data, file_data, ext_data = sct.extract_fname(param.fname_data)

    # Get output folder and file name
    if param.fname_out == '':
        param.fname_out = param.file_prefix+file_data+ext_data

    # create temporary folder
    sct.printv('\nCreate temporary folder...', param.verbose)
    path_tmp = sct.tmp_create(param.verbose)
    # )sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1)
    # sct.run('mkdir '+path_tmp, param.verbose)

    sct.printv('\nCheck orientation...', param.verbose)
    orientation_input = get_orientation(Image(param.fname_data))
    sct.printv('.. '+orientation_input, param.verbose)
    reorient_coordinates = False

    # copy input data to tmp folder
    convert(param.fname_data, path_tmp+'data.nii')
    if method_type == 'centerline':
        convert(method_val, path_tmp+'centerline.nii.gz')
    if method_type == 'point':
        convert(method_val, path_tmp+'point.nii.gz')

    # go to tmp folder
    os.chdir(path_tmp)

    # reorient to RPI
    sct.printv('\nReorient to RPI...', param.verbose)
    # if not orientation_input == 'RPI':
    sct.run('sct_image -i data.nii -o data_RPI.nii -setorient RPI -v 0', verbose=False)
    if method_type == 'centerline':
        sct.run('sct_image -i centerline.nii.gz -o centerline_RPI.nii.gz -setorient RPI -v 0', verbose=False)
    if method_type == 'point':
        sct.run('sct_image -i point.nii.gz -o point_RPI.nii.gz -setorient RPI -v 0', verbose=False)
    #
    # if method_type == 'centerline':
    #     orientation_centerline = get_orientation_3d(method_val, filename=True)
    #     if not orientation_centerline == 'RPI':
    #         sct.run('sct_image -i ' + method_val + ' -o ' + path_tmp + 'centerline.nii.gz' + ' -setorient RPI -v 0', verbose=False)
    #     else:
    #         convert(method_val, path_tmp+'centerline.nii.gz')

    # Get dimensions of data
    sct.printv('\nGet dimensions of data...', param.verbose)
    nx, ny, nz, nt, px, py, pz, pt = Image('data_RPI.nii').dim
    sct.printv('  ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz)+ ' x ' + str(nt), param.verbose)
    # in case user input 4d data
    if nt != 1:
        sct.printv('WARNING in '+os.path.basename(__file__)+': Input image is 4d but output mask will 3D.', param.verbose, 'warning')
        # extract first volume to have 3d reference
        nii = Image('data_RPI.nii')
        data3d = nii.data[:,:,:,0]
        nii.data = data3d
        nii.save()

    if method_type == 'coord':
        # parse to get coordinate
        coord = map(int, method_val.split('x'))

    if method_type == 'point':
        # get file name
        fname_point = method_val
        # extract coordinate of point
        sct.printv('\nExtract coordinate of point...', param.verbose)
        # TODO: change this way to remove dependence to sct.run. ProcessLabels.display_voxel returns list of coordinates
        status, output = sct.run('sct_label_utils -i point_RPI.nii.gz -display', param.verbose)
        # parse to get coordinate
        coord = output[output.find('Position=')+10:-17].split(',')

    if method_type == 'center':
        # set coordinate at center of FOV
        coord = round(float(nx)/2), round(float(ny)/2)

    if method_type == 'centerline':
        # get name of centerline from user argument
        fname_centerline = 'centerline_RPI.nii.gz'
    else:
        # generate volume with line along Z at coordinates 'coord'
        sct.printv('\nCreate line...', param.verbose)
        fname_centerline = create_line('data_RPI.nii', coord, nz)

    # create mask
    sct.printv('\nCreate mask...', param.verbose)
    centerline = nibabel.load(fname_centerline)  # open centerline
    hdr = centerline.get_header()  # get header
    hdr.set_data_dtype('uint8')  # set imagetype to uint8
    spacing = hdr.structarr['pixdim']
    data_centerline = centerline.get_data()  # get centerline
    z_centerline_not_null = [iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any()]
    # get center of mass of the centerline
    cx = [0] * nz
    cy = [0] * nz
    for iz in range(0, nz, 1):
        if iz in z_centerline_not_null:
            cx[iz], cy[iz] = ndimage.measurements.center_of_mass(numpy.array(data_centerline[:, :, iz]))
    # create 2d masks
    file_mask = 'data_mask'
    for iz in range(nz):
        if iz not in z_centerline_not_null:
            # write an empty nifty volume
            img = nibabel.Nifti1Image(data_centerline[:, :, iz], None, hdr)
            nibabel.save(img, (file_mask + str(iz) + '.nii'))
        else:
            center = numpy.array([cx[iz], cy[iz]])
            mask2d = create_mask2d(center, param.shape, param.size, nx, ny, even=param.even, spacing=spacing)
            # Write NIFTI volumes
            img = nibabel.Nifti1Image(mask2d, None, hdr)
            nibabel.save(img, (file_mask+str(iz)+'.nii'))
    # merge along Z
    # cmd = 'fslmerge -z mask '

    # CHANGE THAT CAN IMPACT SPEED:
    # related to issue #755, we cannot open more than 256 files at one time.
    # to solve this issue, we do not open more than 100 files
    '''
    im_list = []
    im_temp = []
    for iz in range(nz_not_null):
        if iz != 0 and iz % 100 == 0:
            im_temp.append(concat_data(im_list, 2))
            im_list = [Image(file_mask + str(iz) + '.nii')]
        else:
            im_list.append(Image(file_mask+str(iz)+'.nii'))

    if im_temp:
        im_temp.append(concat_data(im_list, 2))
        im_out = concat_data(im_temp, 2, no_expand=True)
    else:
        im_out = concat_data(im_list, 2)
    '''
    fname_list = [file_mask + str(iz) + '.nii' for iz in range(nz)]
    im_out = concat_data(fname_list, dim=2)
    im_out.setFileName('mask_RPI.nii.gz')
    im_out.save()

    # reorient if necessary
    # if not orientation_input == 'RPI':
    sct.run('sct_image -i mask_RPI.nii.gz -o mask.nii.gz -setorient ' + orientation_input, param.verbose)

    # copy header input --> mask
    im_dat = Image('data.nii')
    im_mask = Image('mask.nii.gz')
    im_mask = copy_header(im_dat, im_mask)
    im_mask.save()

    # come back to parent folder
    os.chdir('..')

    # Generate output files
    sct.printv('\nGenerate output files...', param.verbose)
    sct.generate_output_file(path_tmp+'mask.nii.gz', param.fname_out)

    # Remove temporary files
    if param.remove_tmp_files == 1:
        sct.printv('\nRemove temporary files...', param.verbose)
        sct.run('rm -rf '+path_tmp, param.verbose, error_exit='warning')

    # to view results
    sct.printv('\nDone! To view results, type:', param.verbose)
    sct.printv('fslview '+param.fname_data+' '+param.fname_out+' -l Red -t 0.5 &', param.verbose, 'info')
    print
    def execute(self):
        print 'Execution of the SCAD algorithm in ' + str(os.getcwd())

        original_name = self.input_image.file_name
        vesselness_file_name = "imageVesselNessFilter.nii.gz"
        raw_file_name = "raw.nii"

        self.setup_debug_folder()

        if self.debug:
            import matplotlib.pyplot as plt  # import for debug purposes

        # create tmp and copy input
        path_tmp = self.create_temporary_path()
        conv.convert(self.input_image.absolutepath, path_tmp + raw_file_name)

        if self.vesselness_provided:
            sct.run('cp ' + vesselness_file_name + ' ' + path_tmp +
                    vesselness_file_name)
        os.chdir(path_tmp)

        # get input image information
        img = Image(raw_file_name)

        # save original orientation and change image to RPI
        self.raw_orientation = img.change_orientation()

        # get body symmetry
        if self.enable_symmetry:
            from msct_image import change_data_orientation
            sym = SymmetryDetector(raw_file_name, self.contrast, crop_xy=0)
            self.raw_symmetry = sym.execute()
            img.change_orientation(self.raw_orientation)
            self.output_debug_file(img, self.raw_symmetry, "body_symmetry")
            img.change_orientation()

        # vesselness filter
        if not self.vesselness_provided:
            sct.run('isct_vesselness -i ' + raw_file_name + ' -t ' +
                    self._contrast + " -radius " + str(self.spinalcord_radius))

        # load vesselness filter data and perform minimum path on it
        img = Image(vesselness_file_name)
        self.output_debug_file(img, img.data, "Vesselness_Filter")
        img.change_orientation()
        self.minimum_path_data, self.J1_min_path, self.J2_min_path = get_minimum_path(
            img.data, invert=1, debug=1)
        self.output_debug_file(img, self.minimum_path_data, "minimal_path")
        self.output_debug_file(img, self.J1_min_path, "J1_minimal_path")
        self.output_debug_file(img, self.J2_min_path, "J2_minimal_path")

        # Apply an exponent to the minimum path
        self.minimum_path_powered = np.power(self.minimum_path_data,
                                             self.minimum_path_exponent)
        self.output_debug_file(
            img, self.minimum_path_powered,
            "minimal_path_power_" + str(self.minimum_path_exponent))

        # Saving in Image since smooth_minimal_path needs pixel dimensions
        img.data = self.minimum_path_powered

        # smooth resulting minimal path
        self.smoothed_min_path = smooth_minimal_path(img)
        self.output_debug_file(img, self.smoothed_min_path.data,
                               "minimal_path_smooth")

        # normalise symmetry values between 0 and 1
        if self.enable_symmetry:
            normalised_symmetry = normalize_array_histogram(self.raw_symmetry)
            self.output_debug_file(img, self.smoothed_min_path.data,
                                   "minimal_path_smooth")

            # multiply normalised symmetry data with the minimum path result
            from msct_image import change_data_orientation
            self.spine_detect_data = np.multiply(
                self.smoothed_min_path.data,
                change_data_orientation(
                    np.power(normalised_symmetry, self.symmetry_exponent),
                    self.raw_orientation, "RPI"))
            self.output_debug_file(img, self.spine_detect_data,
                                   "symmetry_x_min_path")
            # extract the centerline from the minimal path image
            self.centerline_with_outliers = get_centerline(
                self.spine_detect_data, self.spine_detect_data.shape)
        else:
            # extract the centerline from the minimal path image
            self.centerline_with_outliers = get_centerline(
                self.smoothed_min_path.data, self.smoothed_min_path.data.shape)
        self.output_debug_file(img, self.centerline_with_outliers,
                               "centerline_with_outliers")

        # saving centerline with outliers to have
        img.data = self.centerline_with_outliers
        img.change_orientation()
        img.file_name = "centerline_with_outliers"
        img.save()

        # use a b-spline to smooth out the centerline
        x, y, z, dx, dy, dz = smooth_centerline(
            "centerline_with_outliers.nii.gz")

        # save the centerline
        nx, ny, nz, nt, px, py, pz, pt = img.dim
        img.data = np.zeros((nx, ny, nz))
        for i in range(0, np.size(x) - 1):
            img.data[int(x[i]), int(y[i]), int(z[i])] = 1

        self.output_debug_file(img, img.data, "centerline")
        img.change_orientation(self.raw_orientation)
        img.file_name = "centerline"
        img.save()

        # copy back centerline
        os.chdir('../')
        conv.convert(path_tmp + img.file_name + img.ext, self.output_filename)
        if self.rm_tmp_file == 1:
            import shutil
            shutil.rmtree(path_tmp)

        print "To view the output with FSL :"
        sct.printv(
            "fslview " + self.input_image.absolutepath + " " +
            self.output_filename + " -l Red", self.verbose, "info")
Exemplo n.º 49
0
    def execute(self):
        print 'Execution of the SCAD algorithm in '+str(os.getcwd())

        original_name = self.input_image.file_name
        vesselness_file_name = "imageVesselNessFilter.nii.gz"
        raw_file_name = "raw.nii"

        self.setup_debug_folder()

        if self.debug:
            import matplotlib.pyplot as plt # import for debug purposes

        # create tmp and copy input
        path_tmp = self.create_temporary_path()
        conv.convert(self.input_image.absolutepath, path_tmp+raw_file_name)

        if self.vesselness_provided:
            sct.run('cp '+vesselness_file_name+' '+path_tmp+vesselness_file_name)
        os.chdir(path_tmp)

        # get input image information
        img = Image(raw_file_name)

        # save original orientation and change image to RPI
        self.raw_orientation = img.change_orientation()

        # get body symmetry
        if self.enable_symmetry:
            from msct_image import change_data_orientation
            sym = SymmetryDetector(raw_file_name, self.contrast, crop_xy=0)
            self.raw_symmetry = sym.execute()
            img.change_orientation(self.raw_orientation)
            self.output_debug_file(img, self.raw_symmetry, "body_symmetry")
            img.change_orientation()

        # vesselness filter
        if not self.vesselness_provided:
            sct.run('sct_vesselness -i '+raw_file_name+' -t ' + self._contrast+" -radius "+str(self.spinalcord_radius))

        # load vesselness filter data and perform minimum path on it
        img = Image(vesselness_file_name)
        img.change_orientation()
        self.minimum_path_data, self.J1_min_path, self.J2_min_path = get_minimum_path(img.data, invert=1, debug=1)
        self.output_debug_file(img, self.minimum_path_data, "minimal_path")
        self.output_debug_file(img, self.J1_min_path, "J1_minimal_path")
        self.output_debug_file(img, self.J2_min_path, "J2_minimal_path")

        # Apply an exponent to the minimum path
        self.minimum_path_powered = np.power(self.minimum_path_data, self.minimum_path_exponent)
        self.output_debug_file(img, self.minimum_path_powered, "minimal_path_power_"+str(self.minimum_path_exponent))

        # Saving in Image since smooth_minimal_path needs pixel dimensions
        img.data = self.minimum_path_powered

        # smooth resulting minimal path
        self.smoothed_min_path = smooth_minimal_path(img)
        self.output_debug_file(img, self.smoothed_min_path.data, "minimal_path_smooth")

        # normalise symmetry values between 0 and 1
        if self.enable_symmetry:
            normalised_symmetry = normalize_array_histogram(self.raw_symmetry)
            self.output_debug_file(img, self.smoothed_min_path.data, "minimal_path_smooth")

        # multiply normalised symmetry data with the minimum path result
            from msct_image import change_data_orientation
            self.spine_detect_data = np.multiply(self.smoothed_min_path.data, change_data_orientation(np.power(normalised_symmetry, self.symmetry_exponent), self.raw_orientation, "RPI"))
            self.output_debug_file(img, self.spine_detect_data, "symmetry_x_min_path")
            # extract the centerline from the minimal path image
            self.centerline_with_outliers = get_centerline(self.spine_detect_data, self.spine_detect_data.shape)
        else:
            # extract the centerline from the minimal path image
            self.centerline_with_outliers = get_centerline(self.smoothed_min_path.data, self.smoothed_min_path.data.shape)
        self.output_debug_file(img, self.centerline_with_outliers, "centerline_with_outliers")

        # saving centerline with outliers to have
        img.data = self.centerline_with_outliers
        img.change_orientation()
        img.file_name = "centerline_with_outliers"
        img.save()

        # use a b-spline to smooth out the centerline
        x, y, z, dx, dy, dz = smooth_centerline("centerline_with_outliers.nii.gz")

        # save the centerline
        nx, ny, nz, nt, px, py, pz, pt = img.dim
        img.data = np.zeros((nx, ny, nz))
        for i in range(0, np.size(x)-1):
            img.data[int(x[i]), int(y[i]), int(z[i])] = 1

        self.output_debug_file(img, img.data, "centerline")
        img.change_orientation(self.raw_orientation)
        img.file_name = "centerline"
        img.save()

        # copy back centerline
        os.chdir('../')
        conv.convert(path_tmp+img.file_name+img.ext, self.output_filename)
        if self.rm_tmp_file == 1:
            import shutil
            shutil.rmtree(path_tmp)
Exemplo n.º 50
0
def generate_initial_template_space(dataset_info, points_average_centerline, position_template_disks):
    """
    This function generates the initial template space, on which all images will be registered.
    :param points_average_centerline: list of points (x, y, z) of the average spinal cord and brainstem centerline
    :param position_template_disks: index of intervertebral disks along the template centerline
    :return:
    """

    # initializing variables
    path_template = dataset_info['path_template']
    x_size_of_template_space, y_size_of_template_space = 201, 201
    spacing = 0.5

    # creating template space
    size_template_z = int(abs(points_average_centerline[0][2] - points_average_centerline[-1][2]) / spacing) + 15
    template_space = Image([x_size_of_template_space, y_size_of_template_space, size_template_z])
    template_space.data = np.zeros((x_size_of_template_space, y_size_of_template_space, size_template_z))
    template_space.hdr.set_data_dtype('float32')
    origin = [points_average_centerline[-1][0] + x_size_of_template_space * spacing / 2.0,
              points_average_centerline[-1][1] - y_size_of_template_space * spacing / 2.0,
              (points_average_centerline[-1][2] - spacing)]
    template_space.hdr.as_analyze_map()['dim'] = [3.0, x_size_of_template_space, y_size_of_template_space, size_template_z, 1.0, 1.0, 1.0, 1.0]
    template_space.hdr.as_analyze_map()['qoffset_x'] = origin[0]
    template_space.hdr.as_analyze_map()['qoffset_y'] = origin[1]
    template_space.hdr.as_analyze_map()['qoffset_z'] = origin[2]
    template_space.hdr.as_analyze_map()['srow_x'][-1] = origin[0]
    template_space.hdr.as_analyze_map()['srow_y'][-1] = origin[1]
    template_space.hdr.as_analyze_map()['srow_z'][-1] = origin[2]
    template_space.hdr.as_analyze_map()['srow_x'][0] = -spacing
    template_space.hdr.as_analyze_map()['srow_y'][1] = spacing
    template_space.hdr.as_analyze_map()['srow_z'][2] = spacing
    template_space.hdr.set_sform(template_space.hdr.get_sform())
    template_space.hdr.set_qform(template_space.hdr.get_sform())
    template_space.setFileName(path_template + 'template_space.nii.gz')
    template_space.save(type='uint8')

    # generate template centerline as an image
    image_centerline = template_space.copy()
    for coord in points_average_centerline:
        coord_pix = image_centerline.transfo_phys2pix([coord])[0]
        if 0 <= coord_pix[0] < image_centerline.data.shape[0] and 0 <= coord_pix[1] < image_centerline.data.shape[1] and 0 <= coord_pix[2] < image_centerline.data.shape[2]:
            image_centerline.data[int(coord_pix[0]), int(coord_pix[1]), int(coord_pix[2])] = 1
    image_centerline.setFileName(path_template + 'template_centerline.nii.gz')
    image_centerline.save(type='float32')

    # generate template disks position
    coord_physical = []
    image_disks = template_space.copy()
    for disk in position_template_disks:
        label = labels_regions[disk]
        coord = position_template_disks[disk]
        coord_pix = image_disks.transfo_phys2pix([coord])[0]

        coord = coord.tolist()
        coord.append(label)
        coord_physical.append(coord)
        if 0 <= coord_pix[0] < image_disks.data.shape[0] and 0 <= coord_pix[1] < image_disks.data.shape[1] and 0 <= coord_pix[2] < image_disks.data.shape[2]:
            image_disks.data[int(coord_pix[0]), int(coord_pix[1]), int(coord_pix[2])] = label
        else:
            sct.printv(str(coord_pix))
            sct.printv('ERROR: the disk label ' + str(disk) + ' is not in the template image.')
    image_disks.setFileName(path_template + 'template_disks.nii.gz')
    image_disks.save(type='uint8')

    # generate template centerline as a npz file
    x_centerline_fit, y_centerline_fit, z_centerline, x_centerline_deriv, y_centerline_deriv, z_centerline_deriv = smooth_centerline(
        path_template + 'template_centerline.nii.gz', algo_fitting='nurbs', verbose=0, nurbs_pts_number=4000,
        all_slices=False, phys_coordinates=True, remove_outliers=True)
    centerline_template = Centerline(x_centerline_fit, y_centerline_fit, z_centerline,
                                     x_centerline_deriv, y_centerline_deriv, z_centerline_deriv)
    centerline_template.compute_vertebral_distribution(coord_physical)
    centerline_template.save_centerline(fname_output=path_template + 'template_centerline')
Exemplo n.º 51
0
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix, method, file_mask):
    """
    Compute DTI.
    :param fname_in: input 4d file.
    :param bvals: bvals txt file
    :param bvecs: bvecs txt file
    :param prefix: output prefix. Example: "dti_"
    :param method: algo for computing dti
    :return: True/False
    """
    # Open file.
    from msct_image import Image
    nii = Image(fname_in)
    data = nii.data
    print('data.shape (%d, %d, %d, %d)' % data.shape)

    # open bvecs/bvals
    from dipy.io import read_bvals_bvecs
    bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs)
    from dipy.core.gradients import gradient_table
    gtab = gradient_table(bvals, bvecs)

    # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image.
    if not file_mask == '':
        printv('Open mask file...', param.verbose)
        # open mask file
        nii_mask = Image(file_mask)
        mask = nii_mask.data

    # fit tensor model
    printv('Computing tensor using "'+method+'" method...', param.verbose)
    import dipy.reconst.dti as dti
    if method == 'standard':
        tenmodel = dti.TensorModel(gtab)
        if file_mask == '':
            tenfit = tenmodel.fit(data)
        else:
            tenfit = tenmodel.fit(data, mask)
    elif method == 'restore':
        import dipy.denoise.noise_estimate as ne
        sigma = ne.estimate_sigma(data)
        dti_restore = dti.TensorModel(gtab, fit_method='RESTORE', sigma=sigma)
        if file_mask == '':
            tenfit = dti_restore.fit(data)
        else:
            tenfit = dti_restore.fit(data, mask)

    # Compute metrics
    printv('Computing metrics...', param.verbose)
    # FA
    from dipy.reconst.dti import fractional_anisotropy
    nii.data = fractional_anisotropy(tenfit.evals)
    nii.setFileName(prefix+'FA.nii.gz')
    nii.save('float32')
    # MD
    from dipy.reconst.dti import mean_diffusivity
    nii.data = mean_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'MD.nii.gz')
    nii.save('float32')
    # RD
    from dipy.reconst.dti import radial_diffusivity
    nii.data = radial_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'RD.nii.gz')
    nii.save('float32')
    # AD
    from dipy.reconst.dti import axial_diffusivity
    nii.data = axial_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'AD.nii.gz')
    nii.save('float32')

    return True
Exemplo n.º 52
0
def register(src, dest, paramreg, param, i_step_str):

    # initiate default parameters of antsRegistration transformation
    ants_registration_params = {'rigid': '', 'affine': '', 'compositeaffine': '', 'similarity': '', 'translation': '',
                                'bspline': ',10', 'gaussiandisplacementfield': ',3,0',
                                'bsplinedisplacementfield': ',5,10', 'syn': ',3,0', 'bsplinesyn': ',1,3'}
    output = ''  # default output if problem

    # display arguments
    sct.printv('Registration parameters:', param.verbose)
    sct.printv('  type ........... '+paramreg.steps[i_step_str].type, param.verbose)
    sct.printv('  algo ........... '+paramreg.steps[i_step_str].algo, param.verbose)
    sct.printv('  slicewise ...... '+paramreg.steps[i_step_str].slicewise, param.verbose)
    sct.printv('  metric ......... '+paramreg.steps[i_step_str].metric, param.verbose)
    sct.printv('  iter ........... '+paramreg.steps[i_step_str].iter, param.verbose)
    sct.printv('  smooth ......... '+paramreg.steps[i_step_str].smooth, param.verbose)
    sct.printv('  laplacian ...... '+paramreg.steps[i_step_str].laplacian, param.verbose)
    sct.printv('  shrink ......... '+paramreg.steps[i_step_str].shrink, param.verbose)
    sct.printv('  gradStep ....... '+paramreg.steps[i_step_str].gradStep, param.verbose)
    sct.printv('  init ........... '+paramreg.steps[i_step_str].init, param.verbose)
    sct.printv('  poly ........... '+paramreg.steps[i_step_str].poly, param.verbose)
    sct.printv('  dof ............ '+paramreg.steps[i_step_str].dof, param.verbose)
    sct.printv('  smoothWarpXY ... '+paramreg.steps[i_step_str].smoothWarpXY, param.verbose)

    # set metricSize
    if paramreg.steps[i_step_str].metric == 'MI':
        metricSize = '32'  # corresponds to number of bins
    else:
        metricSize = '4'  # corresponds to radius (for CC, MeanSquares...)

    # set masking
    if param.fname_mask:
        fname_mask = 'mask.nii.gz'
        masking = '-x mask.nii.gz'
    else:
        fname_mask = ''
        masking = ''

    if paramreg.steps[i_step_str].algo == 'slicereg':
        # check if user used type=label
        if paramreg.steps[i_step_str].type == 'label':
            sct.printv('\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg', 1, 'error')
        else:
            from msct_image import find_zmin_zmax
            # threshold images (otherwise, automatic crop does not work -- see issue #293)
            src_th = sct.add_suffix(src, '_th')
            from msct_image import Image
            nii = Image(src)
            data = nii.data
            data[data < 0.1] = 0
            nii.data = data
            nii.setFileName(src_th)
            nii.save()
            # sct.run(fsloutput+'fslmaths '+src+' -thr 0.1 '+src_th, param.verbose)
            dest_th = sct.add_suffix(dest, '_th')
            nii = Image(dest)
            data = nii.data
            data[data < 0.1] = 0
            nii.data = data
            nii.setFileName(dest_th)
            nii.save()
            # sct.run(fsloutput+'fslmaths '+dest+' -thr 0.1 '+dest_th, param.verbose)
            # find zmin and zmax
            zmin_src, zmax_src = find_zmin_zmax(src_th)
            zmin_dest, zmax_dest = find_zmin_zmax(dest_th)
            zmin_total = max([zmin_src, zmin_dest])
            zmax_total = min([zmax_src, zmax_dest])
            # crop data
            src_crop = sct.add_suffix(src, '_crop')
            sct.run('sct_crop_image -i '+src+' -o '+src_crop+' -dim 2 -start '+str(zmin_total)+' -end '+str(zmax_total), param.verbose)
            dest_crop = sct.add_suffix(dest, '_crop')
            sct.run('sct_crop_image -i '+dest+' -o '+dest_crop+' -dim 2 -start '+str(zmin_total)+' -end '+str(zmax_total), param.verbose)
            # update variables
            src = src_crop
            dest = dest_crop
            scr_regStep = sct.add_suffix(src, '_regStep'+i_step_str)
            # estimate transfo
            cmd = ('isct_antsSliceRegularizedRegistration '
                   '-t Translation[0.5] '
                   '-m '+paramreg.steps[i_step_str].metric+'['+dest+','+src+',1,'+metricSize+',Regular,0.2] '
                   '-p '+paramreg.steps[i_step_str].poly+' '
                   '-i '+paramreg.steps[i_step_str].iter+' '
                   '-f 1 '
                   '-s '+paramreg.steps[i_step_str].smooth+' '
                   '-v 1 '  # verbose (verbose=2 does not exist, so we force it to 1)
                   '-o [step'+i_step_str+','+scr_regStep+'] '  # here the warp name is stage10 because antsSliceReg add "Warp"
                   +masking)
            warp_forward_out = 'step'+i_step_str+'Warp.nii.gz'
            warp_inverse_out = 'step'+i_step_str+'InverseWarp.nii.gz'
            # run command
            status, output = sct.run(cmd, param.verbose)

    # ANTS 3d
    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params and paramreg.steps[i_step_str].slicewise == '0':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            # Pad the destination image (because ants doesn't deform the extremities)
            # N.B. no need to pad if iter = 0
            if not paramreg.steps[i_step_str].iter == '0':
                dest_pad = sct.add_suffix(dest, '_pad')
                sct.run('sct_image -i '+dest+' -o '+dest_pad+' -pad 0,0,'+str(param.padding))
                dest = dest_pad
            # apply Laplacian filter
            if not paramreg.steps[i_step_str].laplacian == '0':
                sct.printv('\nApply Laplacian filter', param.verbose)
                sct.run('sct_maths -i '+src+' -laplacian '+paramreg.steps[i_step_str].laplacian+','+paramreg.steps[i_step_str].laplacian+',0 -o '+sct.add_suffix(src, '_laplacian'))
                sct.run('sct_maths -i '+dest+' -laplacian '+paramreg.steps[i_step_str].laplacian+','+paramreg.steps[i_step_str].laplacian+',0 -o '+sct.add_suffix(dest, '_laplacian'))
                src = sct.add_suffix(src, '_laplacian')
                dest = sct.add_suffix(dest, '_laplacian')
            # Estimate transformation
            sct.printv('\nEstimate transformation', param.verbose)
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            cmd = ('isct_antsRegistration '
                   '--dimensionality 3 '
                   '--transform '+paramreg.steps[i_step_str].algo+'['+paramreg.steps[i_step_str].gradStep +
                   ants_registration_params[paramreg.steps[i_step_str].algo.lower()]+'] '
                   '--metric '+paramreg.steps[i_step_str].metric+'['+dest+','+src+',1,'+metricSize+'] '
                   '--convergence '+paramreg.steps[i_step_str].iter+' '
                   '--shrink-factors '+paramreg.steps[i_step_str].shrink+' '
                   '--smoothing-sigmas '+paramreg.steps[i_step_str].smooth+'mm '
                   '--restrict-deformation 1x1x0 '
                   '--output [step'+i_step_str+','+scr_regStep+'] '
                   '--interpolation BSpline[3] '
                   +masking)
            # add verbose
            if param.verbose >= 1:
                cmd += ' --verbose 1'
            # add init translation
            if not paramreg.steps[i_step_str].init == '':
                init_dict = {'geometric': '0', 'centermass': '1', 'origin': '2'}
                cmd += ' -r ['+dest+','+src+','+init_dict[paramreg.steps[i_step_str].init]+']'
            # run command
            status, output = sct.run(cmd, param.verbose)
            # get appropriate file name for transformation
            if paramreg.steps[i_step_str].algo in ['rigid', 'affine', 'translation']:
                warp_forward_out = 'step'+i_step_str+'0GenericAffine.mat'
                warp_inverse_out = '-step'+i_step_str+'0GenericAffine.mat'
            else:
                warp_forward_out = 'step'+i_step_str+'0Warp.nii.gz'
                warp_inverse_out = 'step'+i_step_str+'0InverseWarp.nii.gz'

    # ANTS 2d
    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params and paramreg.steps[i_step_str].slicewise == '1':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            from msct_register import register_slicewise
            # if shrink!=1, force it to be 1 (otherwise, it generates a wrong 3d warping field). TODO: fix that!
            if not paramreg.steps[i_step_str].shrink == '1':
                sct.printv('\nWARNING: when using slicewise with SyN or BSplineSyN, shrink factor needs to be one. Forcing shrink=1.', 1, 'warning')
                paramreg.steps[i_step_str].shrink = '1'
            warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
            register_slicewise(src,
                               dest,
                               paramreg=paramreg.steps[i_step_str],
                               fname_mask=fname_mask,
                               warp_forward_out=warp_forward_out,
                               warp_inverse_out=warp_inverse_out,
                               ants_registration_params=ants_registration_params,
                               path_qc=param.path_qc,
                               verbose=param.verbose)

    # slice-wise transfo
    elif paramreg.steps[i_step_str].algo in ['centermass', 'centermassrot', 'columnwise']:
        # if type=im, sends warning
        if paramreg.steps[i_step_str].type == 'im':
            sct.printv('\nWARNING: algo '+paramreg.steps[i_step_str].algo+' should be used with type=seg.\n', 1, 'warning')
        # if type=label, exit with error
        elif paramreg.steps[i_step_str].type == 'label':
            sct.printv('\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg', 1, 'error')
        # check if user provided a mask-- if so, inform it will be ignored
        if not fname_mask == '':
            sct.printv('\nWARNING: algo '+paramreg.steps[i_step_str].algo+' will ignore the provided mask.\n', 1, 'warning')
        # smooth data
        if not paramreg.steps[i_step_str].smooth == '0':
            sct.printv('\nSmooth data', param.verbose)
            sct.run('sct_maths -i '+src+' -smooth '+paramreg.steps[i_step_str].smooth+','+paramreg.steps[i_step_str].smooth+',0 -o '+sct.add_suffix(src, '_smooth'))
            sct.run('sct_maths -i '+dest+' -smooth '+paramreg.steps[i_step_str].smooth+','+paramreg.steps[i_step_str].smooth+',0 -o '+sct.add_suffix(dest, '_smooth'))
            src = sct.add_suffix(src, '_smooth')
            dest = sct.add_suffix(dest, '_smooth')
        from msct_register import register_slicewise
        warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
        register_slicewise(src,
                           dest,
                           paramreg=paramreg.steps[i_step_str],
                           fname_mask=fname_mask,
                           warp_forward_out=warp_forward_out,
                           warp_inverse_out=warp_inverse_out,
                           ants_registration_params=ants_registration_params,
                           path_qc=param.path_qc,
                           verbose=param.verbose)

    else:
        sct.printv('\nERROR: algo '+paramreg.steps[i_step_str].algo+' does not exist. Exit program\n', 1, 'error')

    # landmark-based registration
    if paramreg.steps[i_step_str].type in ['label']:
        # check if user specified ilabel and dlabel
        # TODO
        warp_forward_out = 'step' + i_step_str + '0GenericAffine.txt'
        warp_inverse_out = '-step' + i_step_str + '0GenericAffine.txt'
        from msct_register_landmarks import register_landmarks
        register_landmarks(src,
                           dest,
                           paramreg.steps[i_step_str].dof,
                           fname_affine=warp_forward_out,
                           verbose=param.verbose,
                           path_qc=param.path_qc)

    if not os.path.isfile(warp_forward_out):
        # no forward warping field for rigid and affine
        sct.printv('\nERROR: file '+warp_forward_out+' doesn\'t exist (or is not a file).\n' + output +
                   '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    elif not os.path.isfile(warp_inverse_out) and paramreg.steps[i_step_str].algo not in ['rigid', 'affine', 'translation'] and paramreg.steps[i_step_str].type not in ['label']:
        # no inverse warping field for rigid and affine
        sct.printv('\nERROR: file '+warp_inverse_out+' doesn\'t exist (or is not a file).\n' + output +
                   '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    else:
        # rename warping fields
        if (paramreg.steps[i_step_str].algo.lower() in ['rigid', 'affine', 'translation'] and paramreg.steps[i_step_str].slicewise == '0'):
            # if ANTs is used with affine/rigid --> outputs .mat file
            warp_forward = 'warp_forward_'+i_step_str+'.mat'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_'+i_step_str+'.mat'
        elif paramreg.steps[i_step_str].type in ['label']:
            # if label-based registration is used --> outputs .txt file
            warp_forward = 'warp_forward_'+i_step_str+'.txt'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_'+i_step_str+'.txt'
        else:
            warp_forward = 'warp_forward_'+i_step_str+'.nii.gz'
            warp_inverse = 'warp_inverse_'+i_step_str+'.nii.gz'
            os.rename(warp_forward_out, warp_forward)
            os.rename(warp_inverse_out, warp_inverse)

    return warp_forward, warp_inverse
def main(args=None):

    # Initialization
    # fname_anat = ''
    # fname_centerline = ''
    sigma = 3  # default value of the standard deviation for the Gaussian smoothing (in terms of number of voxels)
    # remove_temp_files = param.remove_temp_files
    # verbose = param.verbose
    start_time = time.time()

    parser = get_parser()
    arguments = parser.parse(sys.argv[1:])

    fname_anat = arguments['-i']
    fname_centerline = arguments['-s']
    if '-smooth' in arguments:
        sigma = arguments['-smooth']
    if '-r' in arguments:
        remove_temp_files = int(arguments['-r'])
    if '-v' in arguments:
        verbose = int(arguments['-v'])

    # Display arguments
    sct.printv('\nCheck input arguments...')
    sct.printv('  Volume to smooth .................. ' + fname_anat)
    sct.printv('  Centerline ........................ ' + fname_centerline)
    sct.printv('  Sigma (mm) ........................ ' + str(sigma))
    sct.printv('  Verbose ........................... ' + str(verbose))

    # Check that input is 3D:
    from msct_image import Image
    nx, ny, nz, nt, px, py, pz, pt = Image(fname_anat).dim
    dim = 4  # by default, will be adjusted later
    if nt == 1:
        dim = 3
    if nz == 1:
        dim = 2
    if dim == 4:
        sct.printv('WARNING: the input image is 4D, please split your image to 3D before smoothing spinalcord using :\n'
                   'sct_image -i ' + fname_anat + ' -split t -o ' + fname_anat, verbose, 'warning')
        sct.printv('4D images not supported, aborting ...', verbose, 'error')

    # Extract path/file/extension
    path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat)
    path_centerline, file_centerline, ext_centerline = sct.extract_fname(fname_centerline)

    path_tmp = sct.tmp_create(basename="smooth_spinalcord", verbose=verbose)

    # Copying input data to tmp folder
    sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose)
    sct.copy(fname_anat, os.path.join(path_tmp, "anat" + ext_anat))
    sct.copy(fname_centerline, os.path.join(path_tmp, "centerline" + ext_centerline))

    # go to tmp folder
    curdir = os.getcwd()
    os.chdir(path_tmp)

    # convert to nii format
    convert('anat' + ext_anat, 'anat.nii')
    convert('centerline' + ext_centerline, 'centerline.nii')

    # Change orientation of the input image into RPI
    sct.printv('\nOrient input volume to RPI orientation...')
    fname_anat_rpi = set_orientation('anat.nii', 'RPI', filename=True)
    shutil.move(fname_anat_rpi, 'anat_rpi.nii')
    # Change orientation of the input image into RPI
    sct.printv('\nOrient centerline to RPI orientation...')
    fname_centerline_rpi = set_orientation('centerline.nii', 'RPI', filename=True)
    shutil.move(fname_centerline_rpi, 'centerline_rpi.nii')

    # Straighten the spinal cord
    # straighten segmentation
    sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose)
    cache_sig = sct.cache_signature(
     input_files=["anat_rpi.nii", "centerline_rpi.nii"],
     input_params={"x": "spline"},
    )
    cachefile = os.path.join(curdir, "straightening.cache")
    if sct.cache_valid(cachefile, cache_sig) and os.path.isfile(os.path.join(curdir, 'warp_curve2straight.nii.gz')) and os.path.isfile(os.path.join(curdir, 'warp_straight2curve.nii.gz')) and os.path.isfile(os.path.join(curdir, 'straight_ref.nii.gz')):
        # if they exist, copy them into current folder
        sct.printv('Reusing existing warping field which seems to be valid', verbose, 'warning')
        sct.copy(os.path.join(curdir, 'warp_curve2straight.nii.gz'), 'warp_curve2straight.nii.gz')
        sct.copy(os.path.join(curdir, 'warp_straight2curve.nii.gz'), 'warp_straight2curve.nii.gz')
        sct.copy(os.path.join(curdir, 'straight_ref.nii.gz'), 'straight_ref.nii.gz')
        # apply straightening
        sct.run(['sct_apply_transfo', '-i', 'anat_rpi.nii', '-w', 'warp_curve2straight.nii.gz', '-d', 'straight_ref.nii.gz', '-o', 'anat_rpi_straight.nii', '-x', 'spline'], verbose)
    else:
        sct.run(['sct_straighten_spinalcord', '-i', 'anat_rpi.nii', '-s', 'centerline_rpi.nii', '-x', 'spline'], verbose)
        sct.cache_save(cachefile, cache_sig)

    # Smooth the straightened image along z
    sct.printv('\nSmooth the straightened image along z...')
    sct.run(['sct_maths', '-i', 'anat_rpi_straight.nii', '-smooth', '0,0,' + str(sigma), '-o', 'anat_rpi_straight_smooth.nii'], verbose)

    # Apply the reversed warping field to get back the curved spinal cord
    sct.printv('\nApply the reversed warping field to get back the curved spinal cord...')
    sct.run(['sct_apply_transfo', '-i', 'anat_rpi_straight_smooth.nii', '-o', 'anat_rpi_straight_smooth_curved.nii', '-d', 'anat.nii', '-w', 'warp_straight2curve.nii.gz', '-x', 'spline'], verbose)

    # replace zeroed voxels by original image (issue #937)
    sct.printv('\nReplace zeroed voxels by original image...', verbose)
    nii_smooth = Image('anat_rpi_straight_smooth_curved.nii')
    data_smooth = nii_smooth.data
    data_input = Image('anat.nii').data
    indzero = np.where(data_smooth == 0)
    data_smooth[indzero] = data_input[indzero]
    nii_smooth.data = data_smooth
    nii_smooth.setFileName('anat_rpi_straight_smooth_curved_nonzero.nii')
    nii_smooth.save()

    # come back
    os.chdir(curdir)

    # Generate output file
    sct.printv('\nGenerate output file...')
    sct.generate_output_file(os.path.join(path_tmp, "anat_rpi_straight_smooth_curved_nonzero.nii"),
                             file_anat + '_smooth' + ext_anat)

    # Remove temporary files
    if remove_temp_files == 1:
        sct.printv('\nRemove temporary files...')
        sct.rmtree(path_tmp)

    # Display elapsed time
    elapsed_time = time.time() - start_time
    sct.printv('\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's\n')

    sct.display_viewer_syntax([file_anat, file_anat + '_smooth'], verbose=verbose)
import os
import commands
import sys
from shutil import move
# Get path of the toolbox
status, path_sct = commands.getstatusoutput('echo $SCT_DIR')
# Append path that contains scripts, to be able to load modules
sys.path.append(path_sct + '/scripts')
from msct_image import Image
import sct_utils as sct

path_template = '/Users/julien/data/PAM50/template'
folder_PAM50 = 'PAM50/template/'
os.chdir(path_template)
sct.create_folder(folder_PAM50)

for file_template in [
        'MNI-Poly-AMU_T1.nii.gz', 'MNI-Poly-AMU_T2.nii.gz',
        'MNI-Poly-AMU_T2star.nii.gz'
]:
    im = Image(file_template)
    # remove negative values
    data = im.data
    data[data < 0] = 0
    im.data = data
    im.changeType('uint16')
    file_new = file_template.replace('MNI-Poly-AMU', 'PAM50')
    im.setFileName(file_new)
    im.save()
    # move to folder
    move(file_new, folder_PAM50 + file_new)
Exemplo n.º 55
0
    def execute(self):
        print 'Execution of the SCAD algorithm'

        vesselness_file_name = "imageVesselNessFilter.nii.gz"
        raw_file_name = "raw.nii"

        if self.debug:
            import matplotlib.pyplot as plt # import for debug purposes

        # create tmp and copy input
        path_tmp = sct.tmp_create()
        sct.tmp_copy_nifti(self.input_image.absolutepath, path_tmp, raw_file_name)

        if self.vesselness_provided:
            sct.run('cp '+vesselness_file_name+' '+path_tmp+vesselness_file_name)
        os.chdir(path_tmp)

        # get input image information
        img = Image(raw_file_name)

        # save original orientation and change image to RPI
        self.raw_orientation = img.change_orientation()

        # get body symmetry
        sym = SymmetryDetector(raw_file_name, self.contrast, crop_xy=1)
        self.raw_symmetry = sym.execute()

        # vesselness filter
        if not self.vesselness_provided:
            sct.run('sct_vesselness -i '+raw_file_name+' -t ' + self._contrast)

        # load vesselness filter data and perform minimum path on it
        img = Image(vesselness_file_name)
        raw_orientation = img.change_orientation()
        self.minimum_path_data, self.J1_min_path, self.J2_min_path = get_minimum_path(img.data, invert=1, debug=1, smooth_factor=1)

        # Apply an exponent to the minimum path
        self.minimum_path_powered = np.power(self.minimum_path_data, self.minimum_path_exponent)

        # Saving in Image since smooth_minimal_path needs pixel dimensions
        img.data = self.minimum_path_powered

        # smooth resulting minimal path
        self.smoothed_min_path = smooth_minimal_path(img)

        # normalise symmetry values between 0 and 1
        normalised_symmetry = equalize_array_histogram(self.raw_symmetry)

        # multiply normalised symmetry data with the minimum path result
        self.spine_detect_data = np.multiply(self.smoothed_min_path.data, normalised_symmetry)

        # extract the centerline from the minimal path image
        centerline_with_outliers = get_centerline(self.spine_detect_data, self.spine_detect_data.shape)
        img.data = centerline_with_outliers
        img.change_orientation()
        img.file_name = "centerline_with_outliers"
        img.save()

        # use a b-spline to smooth out the centerline
        x, y, z, dx, dy, dz = smooth_centerline("centerline_with_outliers.nii.gz")

        # save the centerline
        centerline_dim = img.dim
        img.data = np.zeros(centerline_dim)
        for i in range(0, np.size(x)-1):
            img.data[int(x[i]), int(y[i]), int(z[i])] = 1

        img.change_orientation(raw_orientation)
        img.file_name = "centerline"
        img.save()

        # copy back centerline
        os.chdir('../')
        sct.tmp_copy_nifti(path_tmp + 'centerline.nii.gz',self.input_image.path,self.input_image.file_name+'_centerline'+self.input_image.ext)

        if self.rm_tmp_file == 1:
            import shutil
            shutil.rmtree(path_tmp)

        if self.produce_output:
            self.produce_output_files()
def dmri_moco(param):

    file_data = 'dmri'
    ext_data = '.nii'
    file_b0 = 'b0'
    file_dwi = 'dwi'
    mat_final = 'mat_final/'
    file_dwi_group = 'dwi_averaged_groups'  # no extension
    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; '  # for faster processing, all outputs are in NIFTI
    ext_mat = 'Warp.nii.gz'  # warping field

    # Get dimensions of data
    sct.printv('\nGet dimensions of data...', param.verbose)
    nx, ny, nz, nt, px, py, pz, pt = Image(file_data+'.nii').dim
    sct.printv('  ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), param.verbose)

    # Identify b=0 and DWI images
    sct.printv('\nIdentify b=0 and DWI images...', param.verbose)
    index_b0, index_dwi, nb_b0, nb_dwi = identify_b0('bvecs.txt', param.fname_bvals, param.bval_min, param.verbose)

    # check if dmri and bvecs are the same size
    if not nb_b0 + nb_dwi == nt:
        sct.printv('\nERROR in '+os.path.basename(__file__)+': Size of data ('+str(nt)+') and size of bvecs ('+str(nb_b0+nb_dwi)+') are not the same. Check your bvecs file.\n', 1, 'error')
        sys.exit(2)

    # Prepare NIFTI (mean/groups...)
    #===================================================================================================================
    # Split into T dimension
    sct.printv('\nSplit along T dimension...', param.verbose)
    status, output = sct.run('sct_split_data -i ' + file_data + ext_data + ' -dim t -suffix _T', param.verbose)

    # Merge b=0 images
    sct.printv('\nMerge b=0...', param.verbose)
    # cmd = fsloutput + 'fslmerge -t ' + file_b0
    # for it in range(nb_b0):
    #     cmd = cmd + ' ' + file_data + '_T' + str(index_b0[it]).zfill(4)
    cmd = 'sct_concat_data -dim t -o ' + file_b0 + ext_data + ' -i '
    for it in range(nb_b0):
        cmd = cmd + file_data + '_T' + str(index_b0[it]).zfill(4) + ext_data + ','
    cmd = cmd[:-1]  # remove ',' at the end of the string
    status, output = sct.run(cmd, param.verbose)
    sct.printv(('  File created: ' + file_b0), param.verbose)

    # Average b=0 images
    sct.printv('\nAverage b=0...', param.verbose)
    file_b0_mean = file_b0+'_mean'
    sct.run('sct_maths -i '+file_b0+'.nii'+' -o '+file_b0_mean+'.nii'+' -mean t', param.verbose)
    # if not average_data_across_dimension(file_b0+'.nii', file_b0_mean+'.nii', 3):
    #     sct.printv('ERROR in average_data_across_dimension', 1, 'error')
    # cmd = fsloutput + 'fslmaths ' + file_b0 + ' -Tmean ' + file_b0_mean
    # status, output = sct.run(cmd, param.verbose)

    # Number of DWI groups
    nb_groups = int(math.floor(nb_dwi/param.group_size))
    
    # Generate groups indexes
    group_indexes = []
    for iGroup in range(nb_groups):
        group_indexes.append(index_dwi[(iGroup*param.group_size):((iGroup+1)*param.group_size)])
    
    # add the remaining images to the last DWI group
    nb_remaining = nb_dwi%param.group_size  # number of remaining images
    if nb_remaining > 0:
        nb_groups += 1
        group_indexes.append(index_dwi[len(index_dwi)-nb_remaining:len(index_dwi)])

    # DWI groups
    for iGroup in range(nb_groups):
        sct.printv('\nDWI group: ' +str((iGroup+1))+'/'+str(nb_groups), param.verbose)

        # get index
        index_dwi_i = group_indexes[iGroup]
        nb_dwi_i = len(index_dwi_i)

        # Merge DW Images
        sct.printv('Merge DW images...', param.verbose)
        file_dwi_merge_i = file_dwi + '_' + str(iGroup)
        cmd = 'sct_concat_data -dim t -o ' + file_dwi_merge_i + ext_data + ' -i '
        for it in range(nb_dwi_i):
            cmd = cmd + file_data + '_T' + str(index_dwi_i[it]).zfill(4) + ext_data + ','
        cmd = cmd[:-1]  # remove ',' at the end of the string
        sct.run(cmd, param.verbose)
        # cmd = fsloutput + 'fslmerge -t ' + file_dwi_merge_i
        # for it in range(nb_dwi_i):
        #     cmd = cmd +' ' + file_data + '_T' + str(index_dwi_i[it]).zfill(4)

        # Average DW Images
        sct.printv('Average DW images...', param.verbose)
        file_dwi_mean = file_dwi + '_mean_' + str(iGroup)
        sct.run('sct_maths -i '+file_dwi_merge_i+'.nii'+' -o '+file_dwi_mean+'.nii'+' -mean t', param.verbose)
        # if not average_data_across_dimension(file_dwi_merge_i+'.nii', file_dwi_mean+'.nii', 3):
        #     sct.printv('ERROR in average_data_across_dimension', 1, 'error')
        # cmd = fsloutput + 'fslmaths ' + file_dwi_merge_i + ' -Tmean ' + file_dwi_mean
        # sct.run(cmd, param.verbose)

    # Merge DWI groups means
    sct.printv('\nMerging DW files...', param.verbose)
    # file_dwi_groups_means_merge = 'dwi_averaged_groups'
    cmd = 'sct_concat_data -dim t -o ' + file_dwi_group + ext_data + ' -i '
    for iGroup in range(nb_groups):
        cmd = cmd + file_dwi + '_mean_' + str(iGroup) + ext_data + ','
    cmd = cmd[:-1]  # remove ',' at the end of the string
    sct.run(cmd, param.verbose)
    # cmd = fsloutput + 'fslmerge -t ' + file_dwi_group
    # for iGroup in range(nb_groups):
    #     cmd = cmd + ' ' + file_dwi + '_mean_' + str(iGroup)

    # Average DW Images
    # TODO: USEFULL ???
    sct.printv('\nAveraging all DW images...', param.verbose)
    fname_dwi_mean = 'dwi_mean'
    sct.run('sct_maths -i '+file_dwi_group+'.nii'+' -o '+file_dwi_group+'_mean.nii'+' -mean t', param.verbose)
    # if not average_data_across_dimension(file_dwi_group+'.nii', file_dwi_group+'_mean.nii', 3):
    #     sct.printv('ERROR in average_data_across_dimension', 1, 'error')
    # sct.run(fsloutput + 'fslmaths ' + file_dwi_group + ' -Tmean ' + file_dwi_group+'_mean', param.verbose)

    # segment dwi images using otsu algorithm
    if param.otsu:
        sct.printv('\nSegment group DWI using OTSU algorithm...', param.verbose)
        # import module
        otsu = importlib.import_module('sct_otsu')
        # get class from module
        param_otsu = otsu.param()  #getattr(otsu, param)
        param_otsu.fname_data = file_dwi_group+'.nii'
        param_otsu.threshold = param.otsu
        param_otsu.file_suffix = '_seg'
        # run otsu
        otsu.otsu(param_otsu)
        file_dwi_group = file_dwi_group+'_seg'

    # extract first DWI volume as target for registration
    nii = Image(file_dwi_group+'.nii')
    data_crop = nii.data[:, :, :, index_dwi[0]:index_dwi[0]+1]
    nii.data = data_crop
    nii.setFileName('target_dwi.nii')
    nii.save()


    # START MOCO
    #===================================================================================================================

    # Estimate moco on b0 groups
    sct.printv('\n-------------------------------------------------------------------------------', param.verbose)
    sct.printv('  Estimating motion on b=0 images...', param.verbose)
    sct.printv('-------------------------------------------------------------------------------', param.verbose)
    param_moco = param
    param_moco.file_data = 'b0'
    if index_dwi[0] != 0:
        # If first DWI is not the first volume (most common), then there is a least one b=0 image before. In that case
        # select it as the target image for registration of all b=0
        param_moco.file_target = file_data + '_T' + str(index_b0[index_dwi[0]-1]).zfill(4)
    else:
        # If first DWI is the first volume, then the target b=0 is the first b=0 from the index_b0.
        param_moco.file_target = file_data + '_T' + str(index_b0[0]).zfill(4)
    param_moco.path_out = ''
    param_moco.todo = 'estimate'
    param_moco.mat_moco = 'mat_b0groups'
    moco.moco(param_moco)

    # Estimate moco on dwi groups
    sct.printv('\n-------------------------------------------------------------------------------', param.verbose)
    sct.printv('  Estimating motion on DW images...', param.verbose)
    sct.printv('-------------------------------------------------------------------------------', param.verbose)
    param_moco.file_data = file_dwi_group
    param_moco.file_target = 'target_dwi'  # target is the first DW image (closest to the first b=0)
    param_moco.path_out = ''
    #param_moco.todo = 'estimate'
    param_moco.todo = 'estimate_and_apply'
    param_moco.mat_moco = 'mat_dwigroups'
    moco.moco(param_moco)

    # create final mat folder
    sct.create_folder(mat_final)

    # Copy b=0 registration matrices
    sct.printv('\nCopy b=0 registration matrices...', param.verbose)

    for it in range(nb_b0):
        sct.run('cp '+'mat_b0groups/'+'mat.T'+str(it)+ext_mat+' '+mat_final+'mat.T'+str(index_b0[it])+ext_mat, param.verbose)

    # Copy DWI registration matrices
    sct.printv('\nCopy DWI registration matrices...', param.verbose)
    for iGroup in range(nb_groups):
        for dwi in range(len(group_indexes[iGroup])):
            sct.run('cp '+'mat_dwigroups/'+'mat.T'+str(iGroup)+ext_mat+' '+mat_final+'mat.T'+str(group_indexes[iGroup][dwi])+ext_mat, param.verbose)

    # Spline Regularization along T
    if param.spline_fitting:
        moco.spline(mat_final, nt, nz, param.verbose, np.array(index_b0), param.plot_graph)

    # combine Eddy Matrices
    if param.run_eddy:
        param.mat_2_combine = 'mat_eddy'
        param.mat_final = mat_final
        moco.combine_matrix(param)

    # Apply moco on all dmri data
    sct.printv('\n-------------------------------------------------------------------------------', param.verbose)
    sct.printv('  Apply moco', param.verbose)
    sct.printv('-------------------------------------------------------------------------------', param.verbose)
    param_moco.file_data = 'dmri'
    param_moco.file_target = file_dwi+'_mean_'+str(0)  # reference for reslicing into proper coordinate system
    param_moco.path_out = ''
    param_moco.mat_moco = mat_final
    param_moco.todo = 'apply'
    moco.moco(param_moco)

    # copy geometric information from header
    # NB: this is required because WarpImageMultiTransform in 2D mode wrongly sets pixdim(3) to "1".
    copy_header('dmri.nii', 'dmri_moco.nii')

    # generate b0_moco_mean and dwi_moco_mean
    cmd = 'sct_dmri_separate_b0_and_dwi -i dmri'+param.suffix+'.nii -b bvecs.txt -a 1'
    if not param.fname_bvals == '':
        cmd = cmd+' -m '+param.fname_bvals
    sct.run(cmd, param.verbose)
Exemplo n.º 57
0
def create_mask():

    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; '  # for faster processing, all outputs are in NIFTI

    # display usage if a mandatory argument is not provided
    if param.fname_data == '' or param.method == '':
        sct.printv('\nERROR: All mandatory arguments are not provided. See usage (add -h).\n', 1, 'error')

    # parse argument for method
    method_list = param.method.replace(' ', '').split(',')  # remove spaces and parse with comma
    # method_list = param.method.split(',')  # parse with comma
    method_type = method_list[0]

    # check existence of method type
    if not method_type in param.method_list:
        sct.printv('\nERROR in '+os.path.basename(__file__)+': Method "'+method_type+'" is not recognized. See usage (add -h).\n', 1, 'error')

    # check method val
    if not method_type == 'center':
        method_val = method_list[1]
    del method_list

    # check existence of shape
    if not param.shape in param.shape_list:
        sct.printv('\nERROR in '+os.path.basename(__file__)+': Shape "'+param.shape+'" is not recognized. See usage (add -h).\n', 1, 'error')

    # check existence of input files
    sct.printv('\ncheck existence of input files...', param.verbose)
    sct.check_file_exist(param.fname_data, param.verbose)
    if method_type == 'centerline':
        sct.check_file_exist(method_val, param.verbose)

    # check if orientation is RPI
    sct.printv('\nCheck if orientation is RPI...', param.verbose)
    status, output = sct.run('sct_orientation -i '+param.fname_data)
    if not output == 'RPI':
        sct.printv('\nERROR in '+os.path.basename(__file__)+': Orientation of input image should be RPI. Use sct_orientation to put your image in RPI.\n', 1, 'error')

    # display input parameters
    sct.printv('\nInput parameters:', param.verbose)
    sct.printv('  data ..................'+param.fname_data, param.verbose)
    sct.printv('  method ................'+method_type, param.verbose)

    # Extract path/file/extension
    path_data, file_data, ext_data = sct.extract_fname(param.fname_data)

    # Get output folder and file name
    if param.fname_out == '':
        param.fname_out = param.file_prefix+file_data+ext_data
    #fname_out = os.path.abspath(path_out+file_out+ext_out)

    # create temporary folder
    sct.printv('\nCreate temporary folder...', param.verbose)
    path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1)
    sct.run('mkdir '+path_tmp, param.verbose)

    # Copying input data to tmp folder and convert to nii
    # NB: cannot use c3d here because c3d cannot convert 4D data.
    sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose)
    convert(param.fname_data, path_tmp+'data.nii')
    # sct.run('cp '+param.fname_data+' '+path_tmp+'data'+ext_data, param.verbose)
    if method_type == 'centerline':
        convert(method_val, path_tmp+'centerline.nii.gz')
        # sct.run('isct_c3d '+method_val+' -o '+path_tmp+'/centerline.nii.gz')

    # go to tmp folder
    os.chdir(path_tmp)

    # Get dimensions of data
    sct.printv('\nGet dimensions of data...', param.verbose)
    nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim
    sct.printv('  ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz)+ ' x ' + str(nt), param.verbose)
    # in case user input 4d data
    if nt != 1:
        sct.printv('WARNING in '+os.path.basename(__file__)+': Input image is 4d but output mask will 3D.', param.verbose, 'warning')
        # extract first volume to have 3d reference
        nii = Image('data.nii')
        data3d = nii.data[:,:,:,0]
        nii.data = data3d
        nii.save()

    if method_type == 'coord':
        # parse to get coordinate
        coord = map(int, method_val.split('x'))

    if method_type == 'point':
        # get file name
        fname_point = method_val
        # extract coordinate of point
        sct.printv('\nExtract coordinate of point...', param.verbose)
        status, output = sct.run('sct_label_utils -i '+fname_point+' -t display-voxel', param.verbose)
        # parse to get coordinate
        coord = output[output.find('Position=')+10:-17].split(',')

    if method_type == 'center':
        # set coordinate at center of FOV
        coord = round(float(nx)/2), round(float(ny)/2)

    if method_type == 'centerline':
        # get name of centerline from user argument
        fname_centerline = 'centerline.nii.gz'
    else:
        # generate volume with line along Z at coordinates 'coord'
        sct.printv('\nCreate line...', param.verbose)
        fname_centerline = create_line('data.nii', coord, nz)

    # create mask
    sct.printv('\nCreate mask...', param.verbose)
    centerline = nibabel.load(fname_centerline)  # open centerline
    hdr = centerline.get_header()  # get header
    hdr.set_data_dtype('uint8')  # set imagetype to uint8
    data_centerline = centerline.get_data()  # get centerline
    z_centerline = [iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any()]
    nz = len(z_centerline)
    # get center of mass of the centerline
    cx = [0] * nz
    cy = [0] * nz
    for iz in range(0, nz, 1):
        cx[iz], cy[iz] = ndimage.measurements.center_of_mass(numpy.array(data_centerline[:, :, z_centerline[iz]]))
    # create 2d masks
    file_mask = 'data_mask'
    for iz in range(nz):
        center = numpy.array([cx[iz], cy[iz]])
        mask2d = create_mask2d(center, param.shape, param.size, nx, ny)
        # Write NIFTI volumes
        img = nibabel.Nifti1Image(mask2d, None, hdr)
        nibabel.save(img, (file_mask+str(iz)+'.nii'))
    # merge along Z
    # cmd = 'fslmerge -z mask '
    cmd = 'sct_concat_data -dim z -o mask.nii.gz -i '
    for iz in range(nz):
        cmd = cmd + file_mask+str(iz)+'.nii,'
    # remove ',' at the end of the string
    cmd = cmd[:-1]
    status, output = sct.run(cmd, param.verbose)

    # copy geometry
    copy_header('data.nii', 'mask.nii.gz')

    # come back to parent folder
    os.chdir('..')

    # Generate output files
    sct.printv('\nGenerate output files...', param.verbose)
    sct.generate_output_file(path_tmp+'mask.nii.gz', param.fname_out)

    # Remove temporary files
    if param.remove_tmp_files == 1:
        sct.printv('\nRemove temporary files...', param.verbose)
        sct.run('rm -rf '+path_tmp, param.verbose)

    # to view results
    sct.printv('\nDone! To view results, type:', param.verbose)
    sct.printv('fslview '+param.fname_data+' '+param.fname_out+' -l Red -t 0.5 &', param.verbose, 'info')
    print
Exemplo n.º 58
0
def create_mask():
    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; '  # for faster processing, all outputs are in NIFTI

    # parse argument for method
    method_type = param.process[0]
    # check method val
    if not method_type == 'center':
        method_val = param.process[1]

    # check existence of input files
    if method_type == 'centerline':
        sct.check_file_exist(method_val, param.verbose)

    # Extract path/file/extension
    path_data, file_data, ext_data = sct.extract_fname(param.fname_data)

    # Get output folder and file name
    if param.fname_out == '':
        param.fname_out = param.file_prefix + file_data + ext_data

    # create temporary folder
    sct.printv('\nCreate temporary folder...', param.verbose)
    path_tmp = sct.tmp_create(param.verbose)
    # )sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1)
    # sct.run('mkdir '+path_tmp, param.verbose)

    sct.printv('\nCheck orientation...', param.verbose)
    orientation_input = get_orientation(Image(param.fname_data))
    sct.printv('.. ' + orientation_input, param.verbose)
    reorient_coordinates = False

    # copy input data to tmp folder
    convert(param.fname_data, path_tmp + 'data.nii')
    if method_type == 'centerline':
        convert(method_val, path_tmp + 'centerline.nii.gz')
    if method_type == 'point':
        convert(method_val, path_tmp + 'point.nii.gz')

    # go to tmp folder
    os.chdir(path_tmp)

    # reorient to RPI
    sct.printv('\nReorient to RPI...', param.verbose)
    # if not orientation_input == 'RPI':
    sct.run('sct_image -i data.nii -o data_RPI.nii -setorient RPI -v 0',
            verbose=False)
    if method_type == 'centerline':
        sct.run(
            'sct_image -i centerline.nii.gz -o centerline_RPI.nii.gz -setorient RPI -v 0',
            verbose=False)
    if method_type == 'point':
        sct.run(
            'sct_image -i point.nii.gz -o point_RPI.nii.gz -setorient RPI -v 0',
            verbose=False)
    #
    # if method_type == 'centerline':
    #     orientation_centerline = get_orientation_3d(method_val, filename=True)
    #     if not orientation_centerline == 'RPI':
    #         sct.run('sct_image -i ' + method_val + ' -o ' + path_tmp + 'centerline.nii.gz' + ' -setorient RPI -v 0', verbose=False)
    #     else:
    #         convert(method_val, path_tmp+'centerline.nii.gz')

    # Get dimensions of data
    sct.printv('\nGet dimensions of data...', param.verbose)
    nx, ny, nz, nt, px, py, pz, pt = Image('data_RPI.nii').dim
    sct.printv(
        '  ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt),
        param.verbose)
    # in case user input 4d data
    if nt != 1:
        sct.printv(
            'WARNING in ' + os.path.basename(__file__) +
            ': Input image is 4d but output mask will 3D.', param.verbose,
            'warning')
        # extract first volume to have 3d reference
        nii = Image('data_RPI.nii')
        data3d = nii.data[:, :, :, 0]
        nii.data = data3d
        nii.save()

    if method_type == 'coord':
        # parse to get coordinate
        coord = map(int, method_val.split('x'))

    if method_type == 'point':
        # get file name
        fname_point = method_val
        # extract coordinate of point
        sct.printv('\nExtract coordinate of point...', param.verbose)
        # TODO: change this way to remove dependence to sct.run. ProcessLabels.display_voxel returns list of coordinates
        status, output = sct.run(
            'sct_label_utils -i point_RPI.nii.gz -display', param.verbose)
        # parse to get coordinate
        coord = output[output.find('Position=') + 10:-17].split(',')

    if method_type == 'center':
        # set coordinate at center of FOV
        coord = round(float(nx) / 2), round(float(ny) / 2)

    if method_type == 'centerline':
        # get name of centerline from user argument
        fname_centerline = 'centerline_RPI.nii.gz'
    else:
        # generate volume with line along Z at coordinates 'coord'
        sct.printv('\nCreate line...', param.verbose)
        fname_centerline = create_line('data_RPI.nii', coord, nz)

    # create mask
    sct.printv('\nCreate mask...', param.verbose)
    centerline = nibabel.load(fname_centerline)  # open centerline
    hdr = centerline.get_header()  # get header
    hdr.set_data_dtype('uint8')  # set imagetype to uint8
    spacing = hdr.structarr['pixdim']
    data_centerline = centerline.get_data()  # get centerline
    # if data is 2D, reshape with empty third dimension
    if len(data_centerline.shape) == 2:
        data_centerline_shape = list(data_centerline.shape)
        data_centerline_shape.append(1)
        data_centerline = data_centerline.reshape(data_centerline_shape)
    z_centerline_not_null = [
        iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any()
    ]
    # get center of mass of the centerline
    cx = [0] * nz
    cy = [0] * nz
    for iz in range(0, nz, 1):
        if iz in z_centerline_not_null:
            cx[iz], cy[iz] = ndimage.measurements.center_of_mass(
                numpy.array(data_centerline[:, :, iz]))
    # create 2d masks
    file_mask = 'data_mask'
    for iz in range(nz):
        if iz not in z_centerline_not_null:
            # write an empty nifty volume
            img = nibabel.Nifti1Image(data_centerline[:, :, iz], None, hdr)
            nibabel.save(img, (file_mask + str(iz) + '.nii'))
        else:
            center = numpy.array([cx[iz], cy[iz]])
            mask2d = create_mask2d(center,
                                   param.shape,
                                   param.size,
                                   nx,
                                   ny,
                                   even=param.even,
                                   spacing=spacing)
            # Write NIFTI volumes
            img = nibabel.Nifti1Image(mask2d, None, hdr)
            nibabel.save(img, (file_mask + str(iz) + '.nii'))
    # merge along Z
    # cmd = 'fslmerge -z mask '

    # CHANGE THAT CAN IMPACT SPEED:
    # related to issue #755, we cannot open more than 256 files at one time.
    # to solve this issue, we do not open more than 100 files
    '''
    im_list = []
    im_temp = []
    for iz in range(nz_not_null):
        if iz != 0 and iz % 100 == 0:
            im_temp.append(concat_data(im_list, 2))
            im_list = [Image(file_mask + str(iz) + '.nii')]
        else:
            im_list.append(Image(file_mask+str(iz)+'.nii'))

    if im_temp:
        im_temp.append(concat_data(im_list, 2))
        im_out = concat_data(im_temp, 2, no_expand=True)
    else:
        im_out = concat_data(im_list, 2)
    '''
    fname_list = [file_mask + str(iz) + '.nii' for iz in range(nz)]
    im_out = concat_data(fname_list, dim=2)
    im_out.setFileName('mask_RPI.nii.gz')
    im_out.save()

    # reorient if necessary
    # if not orientation_input == 'RPI':
    sct.run(
        'sct_image -i mask_RPI.nii.gz -o mask.nii.gz -setorient ' +
        orientation_input, param.verbose)

    # copy header input --> mask
    im_dat = Image('data.nii')
    im_mask = Image('mask.nii.gz')
    im_mask = copy_header(im_dat, im_mask)
    im_mask.save()

    # come back to parent folder
    os.chdir('..')

    # Generate output files
    sct.printv('\nGenerate output files...', param.verbose)
    sct.generate_output_file(path_tmp + 'mask.nii.gz', param.fname_out)

    # Remove temporary files
    if param.remove_tmp_files == 1:
        sct.printv('\nRemove temporary files...', param.verbose)
        sct.run('rm -rf ' + path_tmp, param.verbose, error_exit='warning')

    # to view results
    sct.printv('\nDone! To view results, type:', param.verbose)
    sct.printv(
        'fslview ' + param.fname_data + ' ' + param.fname_out +
        ' -l Red -t 0.5 &', param.verbose, 'info')
    print
Exemplo n.º 59
0
def main(args = None):

    dim_list = ['x', 'y', 'z', 't']

    if not args:
        args = sys.argv[1:]

    # Get parser info
    parser = get_parser()
    arguments = parser.parse(args)
    fname_in = arguments["-i"]
    fname_out = arguments["-o"]
    verbose = int(arguments['-v'])

    # Open file(s)
    im = Image(fname_in)
    data = im.data  # 3d or 4d numpy array
    dim = im.dim

    # run command
    if '-otsu' in arguments:
        param = arguments['-otsu']
        data_out = otsu(data, param)

    elif '-otsu_adap' in arguments:
        param = arguments['-otsu_adap']
        data_out = otsu_adap(data, param[0], param[1])

    elif '-otsu_median' in arguments:
        param = arguments['-otsu_median']
        data_out = otsu_median(data, param[0], param[1])

    elif '-thr' in arguments:
        param = arguments['-thr']
        data_out = threshold(data, param)

    elif '-percent' in arguments:
        param = arguments['-percent']
        data_out = perc(data, param)

    elif '-bin' in arguments:
        bin_thr = arguments['-bin']
        data_out = binarise(data, bin_thr=bin_thr)

    elif '-add' in arguments:
        from numpy import sum
        data2 = get_data_or_scalar(arguments["-add"], data)
        data_concat = concatenate_along_4th_dimension(data, data2)
        data_out = sum(data_concat, axis=3)

    elif '-sub' in arguments:
        data2 = get_data_or_scalar(arguments['-sub'], data)
        data_out = data - data2

    elif "-laplacian" in arguments:
        sigmas = arguments["-laplacian"]
        if len(sigmas) == 1:
            sigmas = [sigmas for i in range(len(data.shape))]
        elif len(sigmas) != len(data.shape):
            printv(parser.usage.generate(error='ERROR: -laplacian need the same number of inputs as the number of image dimension OR only one input'))
        # adjust sigma based on voxel size
        sigmas = [sigmas[i] / dim[i+4] for i in range(3)]
        # smooth data
        data_out = laplacian(data, sigmas)

    elif '-mul' in arguments:
        from numpy import prod
        data2 = get_data_or_scalar(arguments["-mul"], data)
        data_concat = concatenate_along_4th_dimension(data, data2)
        data_out = prod(data_concat, axis=3)

    elif '-div' in arguments:
        from numpy import divide
        data2 = get_data_or_scalar(arguments["-div"], data)
        data_out = divide(data, data2)

    elif '-mean' in arguments:
        from numpy import mean
        dim = dim_list.index(arguments['-mean'])
        if dim+1 > len(np.shape(data)):  # in case input volume is 3d and dim=t
            data = data[..., np.newaxis]
        data_out = mean(data, dim)

    elif '-std' in arguments:
        from numpy import std
        dim = dim_list.index(arguments['-std'])
        if dim+1 > len(np.shape(data)):  # in case input volume is 3d and dim=t
            data = data[..., np.newaxis]
        data_out = std(data, dim)

    elif "-smooth" in arguments:
        sigmas = arguments["-smooth"]
        if len(sigmas) == 1:
            sigmas = [sigmas[0] for i in range(len(data.shape))]
        elif len(sigmas) != len(data.shape):
            printv(parser.usage.generate(error='ERROR: -smooth need the same number of inputs as the number of image dimension OR only one input'))
        # adjust sigma based on voxel size
        sigmas = [sigmas[i] / dim[i+4] for i in range(3)]
        # smooth data
        data_out = smooth(data, sigmas)

    elif '-dilate' in arguments:
        data_out = dilate(data, arguments['-dilate'])

    elif '-erode' in arguments:
        data_out = erode(data, arguments['-erode'])

    elif '-denoise' in arguments:
        # parse denoising arguments
        p, b = 1, 5  # default arguments
        list_denoise = arguments['-denoise']
        for i in list_denoise:
            if 'p' in i:
                p = int(i.split('=')[1])
            if 'b' in i:
                b = int(i.split('=')[1])
        data_out = denoise_nlmeans(data, patch_radius=p, block_radius=b)

    elif '-symmetrize' in arguments:
        data_out = (data + data[range(data.shape[0]-1, -1, -1), :, :]) / float(2)

    elif '-mi' in arguments:
        # input 1 = from flag -i --> im
        # input 2 = from flag -mi
        im_2 = Image(arguments['-mi'])
        compute_similarity(im.data, im_2.data, fname_out, metric='mi', verbose=verbose)

        data_out=None

    elif '-corr' in arguments:
        # input 1 = from flag -i --> im
        # input 2 = from flag -mi
        im_2 = Image(arguments['-corr'])
        compute_similarity(im.data, im_2.data, fname_out, metric='corr', verbose=verbose)

        data_out=None


    # if no flag is set
    else:
        data_out = None
        printv(parser.usage.generate(error='ERROR: you need to specify an operation to do on the input image'))

    if data_out is not None:
        # Write output
        nii_out = Image(fname_in)  # use header of input file
        nii_out.data = data_out
        nii_out.setFileName(fname_out)
        nii_out.save()
    # TODO: case of multiple outputs
    # assert len(data_out) == n_out
    # if n_in == n_out:
    #     for im_in, d_out, fn_out in zip(nii, data_out, fname_out):
    #         im_in.data = d_out
    #         im_in.setFileName(fn_out)
    #         if "-w" in arguments:
    #             im_in.hdr.set_intent('vector', (), '')
    #         im_in.save()
    # elif n_out == 1:
    #     nii[0].data = data_out[0]
    #     nii[0].setFileName(fname_out[0])
    #     if "-w" in arguments:
    #             nii[0].hdr.set_intent('vector', (), '')
    #     nii[0].save()
    # elif n_out > n_in:
    #     for dat_out, name_out in zip(data_out, fname_out):
    #         im_out = nii[0].copy()
    #         im_out.data = dat_out
    #         im_out.setFileName(name_out)
    #         if "-w" in arguments:
    #             im_out.hdr.set_intent('vector', (), '')
    #         im_out.save()
    # else:
    #     printv(parser.usage.generate(error='ERROR: not the correct numbers of inputs and outputs'))

    # display message
    if data_out is not None:
        printv('\nDone! To view results, type:', verbose)
        printv('fslview '+fname_out+' &\n', verbose, 'info')
    else:
        printv('\nDone! File created: '+fname_out, verbose, 'info')