Esempio n. 1
0
def get_Tmean(in_file_path):
    with tempfile.TemporaryDirectory() as tmpdirname:
        # tMean_path = f'{tmpdirname}/tMean.nii.gz'
        tMean_path = 'tMean.nii.gz'
        mean_image = MeanImage(in_file=in_file_path, dimension='T', out_file=tMean_path)
        mean_image.run()
        mean_image = nib.load(tMean_path).dataobj
    return mean_image
Esempio n. 2
0
    def get_f_means(self):
        data_selection_func = self.data_selection.loc[
            self.data_selection.datatype == 'func']
        for _, elem in tqdm(data_selection_func.iterrows(),
                            total=len(data_selection_func),
                            postfix='Tmean'):
            in_path = elem.path
            out_dir = self.tmean_dir / f'sub-{elem.subject}' / f'ses-{elem.session}' / elem.datatype
            out_dir.mkdir(parents=True, exist_ok=True)
            out_path = out_dir / elem.path.split('/')[-1]
            mean_image = MeanImage(in_file=in_path,
                                   dimension='T',
                                   out_file=out_path)
            mean_image.run()

            self.data_selection.loc[self.data_selection.path == elem.path,
                                    'tmean_path'] = out_path
Esempio n. 3
0
		st = map(float, f)
	print st
	realigner.inputs.slice_times = st
else:
	# ascend alternate every 2nd slice, starting at 2nd slice
	realigner.inputs.slice_times = 'asc_alt_2_1'	

realigner.inputs.slice_info  = 2
realigner.run() 

# Step#3 get T-mean of rs image after realignment 
fslmaths = MeanImage()
fslmaths.inputs.in_file   = 'corr_rest_roi.nii.gz'
fslmaths.inputs.out_file  = 'mean_corr_rest_roi.nii.gz'
fslmaths.inputs.dimension = 'T'
fslmaths.run()

# Step#4 get binary mask & skull stripped imag
img_StMoco = os.path.abspath('corr_rest_roi.nii.gz')

btr 		     = fsl.BET()
btr.inputs.in_file   = img_StMoco 
btr.inputs.mask      = True
btr.run() 

# Step#5 tsnr calculation on realigned image
tsnr = misc.TSNR()
tsnr.inputs.in_file     = 'corr_rest_roi.nii.gz'
tsnr.inputs.mean_file   = 'corr_rest_roi_tsnr_mean.nii.gz'
tsnr.inputs.tsnr_file   = 'corr_rest_roi_tsnr.nii.gz'
tsnr.inputs.stddev_file = 'corr_rest_roi_tsnr_stddev.nii.gz'
Esempio n. 4
0
def gnl_correction(input,
                   file_bash,
                   file_coeff,
                   python3_env,
                   python2_env,
                   path_output,
                   cleanup=True):
    """
    The purpose of the following function is to correct for gradient nonlinearities. A corrected
    file is written using spline interpolation. The function needs FSL to be included in the search
    path.
    Inputs:
        *input: filename of input image.
        *file_bash: filename of bash script which calls the gradient unwarping toolbox.
        *file_coeff: filename of siemens coefficient file.
        *python3_env: name of python3 virtual environment.
        *python2_env: name of python2 virtual environment.
        *path_output: path where output is written.
        *cleanup: delete intermediate files.

    created by Daniel Haenelt
    Date created: 10-01-2020             
    Last modified: 10-01-2020  
    """
    import os
    import shutil as sh
    import numpy as np
    import nibabel as nb
    from nipype.interfaces.fsl import ConvertWarp, Merge
    from nipype.interfaces.fsl.maths import MeanImage
    from nipype.interfaces.fsl.preprocess import ApplyWarp
    from lib.io.get_filename import get_filename
    from lib.cmap.generate_coordinate_mapping import generate_coordinate_mapping

    # get fileparts
    path, name, ext = get_filename(input)

    # make subfolders
    path_grad = os.path.join(path_output, "grad")
    if not os.path.exists(path_grad):
        os.makedirs(path_grad)

    # parse arguments
    file_output = os.path.join(path_output, name + "_gnlcorr" + ext)
    file_warp = os.path.join(path_grad, "warp.nii.gz")
    file_jacobian = os.path.join(path_grad, "warp_jacobian.nii.gz")

    # run gradient unwarp
    os.system("bash " + file_bash  + \
              " " + python3_env + \
              " " + python2_env + \
              " " + path_grad + \
              " " + input + \
              " trilinear.nii.gz" + \
              " " + file_coeff)

    # now create an appropriate warpfield output (relative convention)
    convertwarp = ConvertWarp()
    convertwarp.inputs.reference = os.path.join(path_grad, "trilinear.nii.gz")
    convertwarp.inputs.warp1 = os.path.join(path_grad, "fullWarp_abs.nii.gz")
    convertwarp.inputs.abswarp = True
    convertwarp.inputs.out_relwarp = True
    convertwarp.inputs.out_file = file_warp
    convertwarp.inputs.args = "--jacobian=" + file_jacobian
    convertwarp.run()

    # convertwarp's jacobian output has 8 frames, each combination of one-sided differences, so average them
    calcmean = MeanImage()
    calcmean.inputs.in_file = file_jacobian
    calcmean.inputs.dimension = "T"
    calcmean.inputs.out_file = file_jacobian
    calcmean.run()

    # apply warp to first volume
    applywarp = ApplyWarp()
    applywarp.inputs.in_file = input
    applywarp.inputs.ref_file = input
    applywarp.inputs.relwarp = True
    applywarp.inputs.field_file = file_warp
    applywarp.inputs.output_type = "NIFTI"
    applywarp.inputs.out_file = file_output
    applywarp.inputs.interp = "spline"
    applywarp.run()

    # normalise warped output image to initial intensity range
    data_img = nb.load(input)
    data_array = data_img.get_fdata()
    max_data = np.max(data_array)
    min_data = np.min(data_array)

    data_img = nb.load(file_output)
    data_array = data_img.get_fdata()
    data_array[data_array < min_data] = 0
    data_array[data_array > max_data] = max_data

    output = nb.Nifti1Image(data_array, data_img.affine, data_img.header)
    nb.save(output, file_output)

    # calculate gradient deviations
    os.system("calc_grad_perc_dev" + \
              " --fullwarp=" + file_warp + \
              " -o " + os.path.join(path_grad,"grad_dev"))

    # merge directions
    merger = Merge()
    merger.inputs.in_files = [
        os.path.join(path_grad, "grad_dev_x.nii.gz"),
        os.path.join(path_grad, "grad_dev_y.nii.gz"),
        os.path.join(path_grad, "grad_dev_z.nii.gz")
    ]
    merger.inputs.dimension = 't'
    merger.inputs.merged_file = os.path.join(path_grad, "grad_dev.nii.gz")
    merger.run()

    # convert from % deviation to absolute
    data_img = nb.load(os.path.join(path_grad, "grad_dev.nii.gz"))
    data_array = data_img.get_fdata()
    data_array = data_array / 100

    output = nb.Nifti1Image(data_array, data_img.affine, data_img.header)
    nb.save(output, os.path.join(path_grad, "grad_dev.nii.gz"))

    # warp coordinate mapping
    generate_coordinate_mapping(input,
                                0,
                                path_grad,
                                suffix="gnl",
                                time=False,
                                write_output=True)

    applywarp = ApplyWarp()
    applywarp.inputs.in_file = os.path.join(path_grad, "cmap_gnl.nii")
    applywarp.inputs.ref_file = input
    applywarp.inputs.relwarp = True
    applywarp.inputs.field_file = file_warp
    applywarp.inputs.out_file = os.path.join(path_grad, "cmap_gnl.nii")
    applywarp.inputs.interp = "trilinear"
    applywarp.inputs.output_type = "NIFTI"
    applywarp.run()

    # clean intermediate files
    if cleanup:
        sh.rmtree(path_grad, ignore_errors=True)
Esempio n. 5
0
def predict_mask(in_file: str,
                 masking_config_path=None,
                 input_type: str = 'anat'):
    """
    The image is first resampled into the resolution of the template space, which has a voxel size of 0.2 × 0.2 × 0.2.
    This is done with the Resample command from the FSL library which is an analysis tool for FMRI, MRI and DTI brain
    imaging data. Then, the image is preprocessed using the preprocessing methods of the model class.
    The predictions of the model are reconstructed to a 3D mask via the command Nifit1Image from nibabel.
    This is done using the same affine space as the input image. The latter is then reshaped into the original shape
    inverting the preprocessing step, either with the opencv resize method or by cropping.
    Additionally, the binary mask is resampled into its original affine space, before being multiplied with the brain
    image to extract the ROI.

    Parameters
    ----------
    in_file : str
        path to the file that is to be masked
    masking_config_path : str
        path to the masking config. The masking config is a json file. All parameters have default values that will
        be set in the "get_masking_opts" method.
        The masking config may contain following parameters (if any of them is not given in the config,
        the default value will be taken from mlebe/masking/config/default_schema.json):
        model_folder_path: str The path to the pretrained model. If not set the default mlebe model will be selected.
        use_cuda: bool
            boolean indicating if cuda will be used for the masking
        visualisation_path: str
            if set, the masking predictions will be saved to this destination.
        crop_values:
            if set, the input bids images will be cropped with given values in the x-y dimensions.
        bias_field_correction: dict
            If set, the input image will be bias corrected before given as input to the model.
            The parameter of the bias correction can be given as a dictionary.
            The default values can be found in the default_schema.json config.
    input_type : str
        either 'func' for CDV or BOLD contrast or 'anat' for T2 contrast

    Returns
    -------
    resampled_mask_path : str
        path to the mask
    nii_path_masked : str
        path to the masked image
    """
    import os
    from os import path
    from pathlib import Path

    import ants
    import nibabel as nib
    import numpy as np
    import pandas as pd
    from ants.registration import resample_image
    from nipype.interfaces.fsl.maths import MeanImage

    from mlebe import log
    from mlebe.masking.utils import get_mask, get_mlebe_models, get_biascorrect_opts_defaults
    from mlebe.masking.utils import remove_outliers, get_masking_opts, crop_bids_image, \
        reconstruct_image, pad_to_shape, get_model_config

    log.info(
        f'Starting masking of {in_file} with config {masking_config_path}.')
    masking_opts = get_masking_opts(masking_config_path, input_type)

    if masking_opts['masked_dir']:
        masked_dir = masking_opts['masked_dir']
        df_selection = pd.read_csv(f'{masked_dir}/data_selection.csv')
        df_selection = df_selection.loc[df_selection.path.str.endswith(
            in_file)]

        nii_path_masked = df_selection.masked_path.item()
        resampled_mask_path = df_selection.mask_path.item()

        assert nii_path_masked, f'nii_path_masked not found for {in_file}'
        assert resampled_mask_path, f'nii_path_masked not found for {resampled_mask_path}'

        assert Path(nii_path_masked).exists(
        ), f'nii_path_masked {nii_path_masked} does not exist.'
        assert Path(resampled_mask_path).exists(
        ), f'resampled_mask_path {resampled_mask_path} does not exist.'

        return nii_path_masked, [resampled_mask_path], resampled_mask_path

    if 'model_folder_path' not in masking_opts or not masking_opts[
            'model_folder_path']:
        # if no model_folder_path is given in the config, the default models are selected.
        masking_opts['model_folder_path'] = get_mlebe_models(input_type)
    model_config = get_model_config(masking_opts)
    input = in_file
    if input_type == 'func':
        tMean_path = 'tMean_.nii.gz'
        mean_image = MeanImage(in_file=input,
                               dimension='T',
                               out_file=tMean_path)
        mean_image.run()
        # command = 'fslmaths {a} -Tmean {b}'.format(a=input, b=tMean_path)
        # log.info(f'Executing command "{command}"')
        # os.system(command)
        assert Path(tMean_path).exists()
        input = tMean_path

    resampled_path = 'resampled_input.nii.gz'
    resampled_nii_path = path.abspath(path.expanduser(resampled_path))
    if masking_opts['testing']:
        resampled_nii = resample_image(ants.image_read(str(input)),
                                       (0.2, 0.2, 0.2), False)
        nib.save(resampled_nii, resampled_nii_path)
    else:
        resample_cmd = 'ResampleImage 3 {input} '.format(
            input=input) + resampled_nii_path + ' 0.2x0.2x0.2'
        os.system(resample_cmd)
        log.info(f'Resample image with "{resample_cmd}"')

    if 'crop_values' in masking_opts and masking_opts['crop_values']:
        crop_bids_image(resampled_nii_path, masking_opts['crop_values'])
    """
    Bias correction
    """
    if 'bias_field_correction' in masking_opts and masking_opts[
            'bias_field_correction']:

        bias_correction_config = get_biascorrect_opts_defaults(masking_opts)
        bias_corrected_path = path.abspath(
            path.expanduser('corrected_input.nii.gz'))

        if masking_opts['testing']:
            convergence_args = bias_correction_config['convergence'].strip(
                '][').split(', ')
            iters = [int(elem) for elem in convergence_args[0].split('x')]
            tol = float(convergence_args[1])
            bias_corrected = ants.n4_bias_field_correction(
                ants.image_read(resampled_nii_path),
                bias_correction_config['bspline_fitting'],
                convergence={
                    'iters': iters,
                    'tol': tol
                },
                shrink_factor=bias_correction_config['shrink_factor'])
            nib.save(bias_corrected, bias_corrected_path)
        else:
            command = 'N4BiasFieldCorrection --bspline-fitting {} -d 3 --input-image {} --convergence {} --output {} ' \
                      '--shrink-factor {}'.format(
                bias_correction_config['bspline_fitting'], resampled_nii_path,
                bias_correction_config['convergence'],
                bias_corrected_path, bias_correction_config['shrink_factor'])

            os.system(command)
            log.info(f'Apply bias correction with "{command}"')

    else:
        bias_corrected_path = resampled_nii_path

    image = nib.load(bias_corrected_path)
    in_file_data = image.get_data()
    """
    Getting the mask
    """
    ori_shape = np.moveaxis(in_file_data, 2, 0).shape
    in_file_data, mask_pred, network_input = get_mask(
        model_config,
        in_file_data,
        ori_shape,
        use_cuda=masking_opts['use_cuda'])

    mask_pred = remove_outliers(mask_pred)
    if 'visualisation_path' in masking_opts and masking_opts[
            'visualisation_path']:
        log.info(f'visualisation_path is {masking_opts["visualisation_path"]}')
        save_visualisation(masking_opts, in_file, network_input, mask_pred)
    """
    Reconstruct to original image size
    """
    resized = reconstruct_image(ori_shape, mask_pred)

    resized_path = 'resized_mask.nii.gz'
    resized_path = path.abspath(path.expanduser(resized_path))
    resized_mask = nib.Nifti1Image(resized, image.affine, image.header)
    nib.save(resized_mask, resized_path)

    # get voxel sizes from input
    input_image = nib.load(input)
    input_img_affine = input_image.affine
    voxel_sizes = nib.affines.voxel_sizes(input_img_affine)

    resampled_mask_path = 'resampled_mask.nii.gz'
    resampled_mask_path = path.abspath(path.expanduser(resampled_mask_path))

    if masking_opts['testing']:
        resized_mask = ants.image_read(resized_path)
        resampled_mask_data = resample_image(
            resized_mask, (voxel_sizes[0], voxel_sizes[1], voxel_sizes[2]),
            False, 1)
    else:
        resample_cmd = 'ResampleImage 3 {input} '.format(
            input=resized_path
        ) + ' ' + resampled_mask_path + ' {x}x{y}x{z} '.format(
            x=voxel_sizes[0], y=voxel_sizes[1], z=voxel_sizes[2]) + ' 0 1'
        log.info(f'Resample image with "{resample_cmd}"')
        os.system(resample_cmd)

        resampled_mask = nib.load(resampled_mask_path)
        resampled_mask_data = resampled_mask.get_data()
    input_image_data = input_image.get_data()
    if resampled_mask_data.shape != input_image_data.shape:
        resampled_mask_data = pad_to_shape(resampled_mask_data,
                                           input_image_data)

    if masking_opts['testing']:
        nib.save(resampled_mask_data, resampled_mask_path)
        resampled_mask_data = resampled_mask_data.numpy()
    else:
        nib.save(
            nib.Nifti1Image(resampled_mask_data, input_image.affine,
                            input_image.header), resampled_mask_path)
    """
    Masking of the input image
    """
    log.info('Masking the input image with the generated mask.')
    masked_image = np.multiply(resampled_mask_data, input_image_data).astype(
        'float32'
    )  # nibabel gives a non-helpful error if trying to save data that has dtype float64
    nii_path_masked = 'masked_output.nii.gz'
    nii_path_masked = path.abspath(path.expanduser(nii_path_masked))
    masked_image = nib.Nifti1Image(masked_image, input_image.affine,
                                   input_image.header)
    nib.save(masked_image, nii_path_masked)

    log.info(f'Masking of input image {in_file} finished successfully.')
    # f/s_biascorrect takes a list as input for the mask while biascorrect takes directly the path
    return nii_path_masked, [resampled_mask_path], resampled_mask_path
Esempio n. 6
0
        st = map(float, f)
    print st
    realigner.inputs.slice_times = st
else:
    # ascend alternate every 2nd slice, starting at 2nd slice
    realigner.inputs.slice_times = 'asc_alt_2_1'

realigner.inputs.slice_info = 2
realigner.run()

# Step#3 get T-mean of rs image after realignment
fslmaths = MeanImage()
fslmaths.inputs.in_file = 'corr_rest_roi.nii.gz'
fslmaths.inputs.out_file = 'mean_corr_rest_roi.nii.gz'
fslmaths.inputs.dimension = 'T'
fslmaths.run()

# Step#4 get binary mask & skull stripped imag
img_StMoco = os.path.abspath('corr_rest_roi.nii.gz')

btr = fsl.BET()
btr.inputs.in_file = img_StMoco
btr.inputs.mask = True
btr.run()

# Step#5 tsnr calculation on realigned image
tsnr = misc.TSNR()
tsnr.inputs.in_file = 'corr_rest_roi.nii.gz'
tsnr.inputs.mean_file = 'corr_rest_roi_tsnr_mean.nii.gz'
tsnr.inputs.tsnr_file = 'corr_rest_roi_tsnr.nii.gz'
tsnr.inputs.stddev_file = 'corr_rest_roi_tsnr_stddev.nii.gz'
Esempio n. 7
0
# merge all gray matter probability map across subjects
gm_merged = os.path.join(outdir, 'gm_prob_merged.nii.gz')

merger = Merge()
merger.inputs.in_files = gm_file_list
merger.inputs.dimension = 't'
merger.inputs.output_type = 'NIFTI_GZ'
merger.inputs.merged_file = gm_merged
merger.run()

# get the average of the merged map
gm_merged_ave = gm_merged[:-7] + '_mean.nii.gz'
print('...average GM map: ', gm_merged_ave)

tmean = MeanImage()
tmean.inputs.in_file = gm_merged
tmean.inputs.dimension = 'T'
tmean.inputs.output_type = 'NIFTI_GZ'
tmean.inputs.out_file = gm_merged_ave
tmean.run()

# binarize the group level gray matter map
gm_mask = gm_merged_ave[:-7] + '_mask_060.nii.gz'

binarize = MathsCommand()
binarize.inputs.args = '-thr  0.60 -bin'
binarize.inputs.in_file = gm_merged_ave
binarize.inputs.out_file = gm_mask
binarize.run()