Example #1
0
def upsample_mask_tissues(in_file):
    """
    To upsample the 1,2,3 compartment segmented volume in SPM
    Args:
        in_file: a list containing the three compartments

    Returns:
    """
    import os
    from nipype.interfaces.freesurfer.preprocess import MRIConvert

    out_file = []

    if isinstance(in_file, basestring):  # just one compartment
        out_mask = os.path.basename(in_file).split('.nii.gz')[0] + '_upsample.nii.gz'
        mc = MRIConvert()
        mc.inputs.in_file = in_file
        mc.inputs.out_file = out_mask
        mc.inputs.vox_size = (1, 1, 1)
        mc.run()

        out_file.append(os.path.abspath(os.path.join(os.getcwd(), out_mask)))
    else: # more than one compartment
        for tissue in in_file:
            out_mask = os.path.basename(tissue).split('.nii.gz')[0] + '_upsample.nii.gz'
            mc = MRIConvert()
            mc.inputs.in_file = tissue
            mc.inputs.out_file = out_mask
            mc.inputs.vox_size = (1, 1, 1)
            mc.run()

            out_file.append(os.path.abspath(os.path.join(os.getcwd(), out_mask)))

    return out_file
Example #2
0
def mgh2nii(filename, path_output, out_type="nii"):
    """
    This function converts a volume file from freesurfer mgh to nifti format.
    Inputs:
        *filename: full path of the input file.
        *path_outupt: path where output is written.
        *out_type: target type of file.
    
    created by Daniel Haenelt
    Date created: 06-01-2020             
    Last modified: 24-07-2020
    """
    import os
    from nipype.interfaces.freesurfer.preprocess import MRIConvert
    from lib.io.get_filename import get_filename

    # get filename
    path, name, ext = get_filename(filename)

    # convert volume to nifti format
    mc = MRIConvert()
    mc.inputs.in_file = filename
    mc.inputs.out_file = os.path.join(path_output, name + "." + out_type)
    mc.inputs.in_type = ext.replace('.', '')
    mc.inputs.out_type = out_type
    mc.run()
Example #3
0
def get_flash2orig(file_flash,
                   file_inv2,
                   file_orig,
                   path_output,
                   cleanup=False):
    """
    This function computes the deformation field for the registration between a partial coverage
    GRE image and the freesurfer orig file. The following steps are performed: (1) set output 
    folder structure, (2) get scanner transform GRE <-> inv2 and inv2 -> orig, (3) generate flash
    cmap, (4) apply scanner transform inv2 -> GRE, (5) get flirt registration GRE -> inv2, (6) apply
    flirt to GRE cmap, (7) apply scanner transform to GRE cmap, (8) apply final deformation to GRE.
    The function needs the FSL environment set.
    Inputs:
        *file_flash: input path for GRE image.
        *file_inv2: input path for MP2RAGE INV2 image.
        *file_orig: input path for freesurfer orig image.
        *path_output: path where output is saved.
        *cleanup: delete intermediate files (boolean).
    
    created by Daniel Haenelt
    Date created: 18-04-2019
    Last modified: 16-05-2019
    """
    import os
    import shutil as sh
    from nipype.interfaces.fsl import FLIRT
    from nipype.interfaces.fsl.preprocess import ApplyXFM
    from nipype.interfaces.freesurfer.preprocess import MRIConvert
    from nighres.registration import apply_coordinate_mappings
    from lib.cmap import generate_coordinate_mapping
    from lib.registration.get_scanner_transform import get_scanner_transform
    """
    set folder structure
    """
    path_temp = os.path.join(path_output, "temp")

    if not os.path.exists(path_output):
        os.makedirs(path_output)

    if not os.path.exists(path_temp):
        os.makedirs(path_temp)

    # copy input files
    sh.copyfile(file_inv2, os.path.join(path_temp, "inv2.nii"))
    sh.copyfile(file_flash, os.path.join(path_temp, "flash.nii"))
    """
    convert orig to nifti
    """
    mc = MRIConvert()
    mc.inputs.in_file = file_orig
    mc.inputs.out_file = os.path.join(path_temp, "orig.nii")
    mc.inputs.in_type = "mgz"
    mc.inputs.out_type = "nii"
    mc.run()
    """
    scanner transformation
    """
    get_scanner_transform(os.path.join(path_temp, "inv2.nii"),
                          os.path.join(path_temp, "flash.nii"), path_temp,
                          False)
    get_scanner_transform(os.path.join(path_temp, "flash.nii"),
                          os.path.join(path_temp, "inv2.nii"), path_temp,
                          False)
    get_scanner_transform(os.path.join(path_temp, "inv2.nii"),
                          os.path.join(path_temp, "orig.nii"), path_temp,
                          False)
    """
    generate coordinate mapping
    """
    generate_coordinate_mapping(os.path.join(path_temp, "flash.nii"), 0,
                                path_temp, "flash", False, True)
    """
    scanner transform inv2 to flash
    """
    apply_coordinate_mappings(
        os.path.join(path_temp, "inv2.nii"),  # input 
        os.path.join(path_temp, "inv2_2_flash_scanner.nii"),  # cmap
        interpolation="linear",  # nearest or linear
        padding="zero",  # closest, zero or max
        save_data=True,  # save output data to file (boolean)
        overwrite=True,  # overwrite existing results (boolean)
        output_dir=path_temp,  # output directory
        file_name=
        "inv2_apply_scanner"  # base name with file extension for output
    )
    """
    flirt flash to inv2
    """
    os.chdir(path_temp)
    flirt = FLIRT()
    flirt.inputs.cost_func = "mutualinfo"
    flirt.inputs.dof = 6
    flirt.inputs.interp = "trilinear"  # trilinear, nearestneighbour, sinc or spline
    flirt.inputs.in_file = os.path.join(path_temp, "flash.nii")
    flirt.inputs.reference = os.path.join(path_temp,
                                          "inv2_apply_scanner_def-img.nii.gz")
    flirt.inputs.output_type = "NIFTI_GZ"
    flirt.inputs.out_file = os.path.join(path_temp,
                                         "flash_apply_flirt_def-img.nii.gz")
    flirt.inputs.out_matrix_file = os.path.join(path_temp, "flirt_matrix.txt")
    flirt.run()
    """
    apply flirt to flash cmap
    """
    applyxfm = ApplyXFM()
    applyxfm.inputs.in_file = os.path.join(path_temp, "cmap_flash.nii")
    applyxfm.inputs.reference = os.path.join(path_temp, "flash.nii")
    applyxfm.inputs.in_matrix_file = os.path.join(path_temp,
                                                  "flirt_matrix.txt")
    applyxfm.inputs.interp = "trilinear"
    applyxfm.inputs.padding_size = 0
    applyxfm.inputs.output_type = "NIFTI_GZ"
    applyxfm.inputs.out_file = os.path.join(path_temp,
                                            "cmap_apply_flirt_def-img.nii.gz")
    applyxfm.inputs.apply_xfm = True
    applyxfm.run()
    """
    apply scanner transform to flash cmap
    """
    apply_coordinate_mappings(
        os.path.join(path_temp, "cmap_apply_flirt_def-img.nii.gz"),
        os.path.join(path_temp, "flash_2_inv2_scanner.nii"),  # cmap 1
        os.path.join(path_temp, "inv2_2_orig_scanner.nii"),  # cmap 2
        interpolation="linear",  # nearest or linear
        padding="zero",  # closest, zero or max
        save_data=True,  # save output data to file (boolean)
        overwrite=True,  # overwrite existing results (boolean)
        output_dir=path_temp,  # output directory
        file_name=
        "cmap_apply_scanner"  # base name with file extension for output
    )
    """
    apply deformation to source image
    """
    apply_coordinate_mappings(
        os.path.join(path_temp, "flash.nii"),  # input 
        os.path.join(path_temp, "cmap_apply_scanner_def-img.nii.gz"),
        interpolation="linear",  # nearest or linear
        padding="zero",  # closest, zero or max
        save_data=True,  # save output data to file (boolean)
        overwrite=True,  # overwrite existing results (boolean)
        output_dir=path_temp,  # output directory
        file_name=
        "flash_apply_deformation"  # base name with file extension for output
    )

    # rename final deformation examples
    os.rename(os.path.join(path_temp, "cmap_apply_scanner_def-img.nii.gz"),
              os.path.join(path_output, "flash2orig.nii.gz"))
    os.rename(
        os.path.join(path_temp, "flash_apply_deformation_def-img.nii.gz"),
        os.path.join(path_output, "flash2orig_example.nii.gz"))

    # clean intermediate files
    if cleanup:
        sh.rmtree(path_temp, ignore_errors=True)
Example #4
0
def get_nuisance_mask(input,
                      pathSPM,
                      deformation,
                      path_output,
                      nerode_white=1,
                      nerode_csf=1,
                      segmentation=True,
                      cleanup=True):
    """
    This function calculates WM and CSF masks in space of the functional time series. It uses SPM
    to compute WM and CSF probability maps. These maps are masked with a skullstrip mask and 
    transformed to native epi space.
    Inputs:
        *input: input anatomy (orig.mgz).
        *pathSPM: path to spm toolbox.
        *deformation: coordinate mapping for ana to epi transformation.
        *path_output: path where output is saved.
        *nerode_white: number of wm mask eroding steps.
        *nerode_csf: number of csf mask eroding steps.
        *segmentation: do not calculate new masks to not rerun everything.
        *cleanup: delete intermediate files.

    created by Daniel Haenelt
    Date created: 01-03-2019
    Last modified: 01-03-2019
    """
    import os
    import shutil as sh
    import nibabel as nb
    from scipy.ndimage.morphology import binary_erosion
    from nipype.interfaces.fsl import BET
    from nipype.interfaces.freesurfer.preprocess import MRIConvert
    from nighres.registration import apply_coordinate_mappings
    from lib.skullstrip.skullstrip_spm12 import skullstrip_spm12

    # make output folder
    if not os.path.exists(path_output):
        os.mkdir(path_output)

    # get filename without file extension of input file
    file = os.path.splitext(os.path.basename(input))[0]

    # convert to nifti format
    mc = MRIConvert()
    mc.inputs.in_file = input
    mc.inputs.out_file = os.path.join(path_output, file + ".nii")
    mc.inputs.out_type = "nii"
    mc.run()

    # bet skullstrip mask
    btr = BET()
    btr.inputs.in_file = os.path.join(path_output, file + ".nii")
    btr.inputs.frac = 0.5
    btr.inputs.mask = True
    btr.inputs.no_output = True
    btr.inputs.out_file = os.path.join(path_output, "bet")
    btr.inputs.output_type = "NIFTI"
    btr.run()

    # segmentation
    if segmentation:
        skullstrip_spm12(os.path.join(path_output, file + ".nii"), pathSPM,
                         path_output)

    # load tissue maps
    wm_array = nb.load(os.path.join(path_output, "skull",
                                    "c2" + file + ".nii")).get_fdata()
    csf_array = nb.load(
        os.path.join(path_output, "skull", "c3" + file + ".nii")).get_fdata()
    mask_array = nb.load(os.path.join(path_output, "bet_mask.nii")).get_fdata()

    # binarize
    wm_array[wm_array > 0] = 1
    csf_array[csf_array > 0] = 1

    # apply brain mask
    wm_array = wm_array * mask_array
    csf_array = csf_array * mask_array

    # erode wm
    wm_array = binary_erosion(
        wm_array,
        structure=None,
        iterations=nerode_white,
        mask=None,
        output=None,
        border_value=0,
        origin=0,
        brute_force=False,
    )

    # erode csf
    csf_array = binary_erosion(
        csf_array,
        structure=None,
        iterations=nerode_csf,
        mask=None,
        output=None,
        border_value=0,
        origin=0,
        brute_force=False,
    )

    # write wm and csf mask
    data_img = nb.load(input)
    wm_out = nb.Nifti1Image(wm_array, data_img.affine, data_img.header)
    nb.save(wm_out, os.path.join(path_output, "wm_mask_orig.nii"))
    csf_out = nb.Nifti1Image(csf_array, data_img.affine, data_img.header)
    nb.save(csf_out, os.path.join(path_output, "csf_mask_orig.nii"))

    # apply deformation to mask
    apply_coordinate_mappings(
        os.path.join(path_output, "wm_mask_orig.nii"),  # input 
        deformation,  # cmap
        interpolation="nearest",  # nearest or linear
        padding="zero",  # closest, zero or max
        save_data=True,  # save output data to file (boolean)
        overwrite=True,  # overwrite existing results (boolean)
        output_dir=path_output,  # output directory
        file_name="wm_mask"  # base name with file extension for output
    )

    apply_coordinate_mappings(
        os.path.join(path_output, "csf_mask_orig.nii"),  # input 
        deformation,  # cmap
        interpolation="nearest",  # nearest or linear
        padding="zero",  # closest, zero or max
        save_data=True,  # save output data to file (boolean)
        overwrite=True,  # overwrite existing results (boolean)
        output_dir=path_output,  # output directory
        file_name="csf_mask"  # base name with file extension for output
    )

    # rename transformed masks
    os.rename(os.path.join(path_output, "wm_mask_def-img.nii.gz"),
              os.path.join(path_output, "wm_mask.nii.gz"))
    os.rename(os.path.join(path_output, "csf_mask_def-img.nii.gz"),
              os.path.join(path_output, "csf_mask.nii.gz"))

    # cleanup
    if cleanup:
        os.remove(os.path.join(path_output, "bet_mask.nii"))
        os.remove(os.path.join(path_output, "csf_mask_orig.nii"))
        os.remove(os.path.join(path_output, "wm_mask_orig.nii"))
        os.remove(os.path.join(path_output, "orig.nii"))
        sh.rmtree(os.path.join(path_output, "skull"), ignore_errors=True)
Example #5
0
def map2surface(input_surf,
                input_vol,
                hemi,
                path_output,
                input_white=None,
                input_ind=None,
                cleanup=True):
    """
    This function samples data from the input volume to the input surface and optionally maps those
    values to a target surface if an index file is given.
    Inputs:
        *input_surf: surface mesh onto which volume data is sampled.
        *input_vol: volume from which data is sampled.
        *hemi: hemisphere.
        *path_output: path where to save output.
        *input_white: white surface in target surface space (only necessary if index file is given).
        *input_ind: textfile with mapping of vertex indices to target space.
        *cleanup: remove intermediate files.
            
    created by Daniel Haenelt
    Date created: 06-02-2019      
    Last modified: 03-08-2020
    """
    import os
    import numpy as np
    import nibabel as nb
    import shutil as sh
    from nibabel.freesurfer.io import read_geometry
    from nipype.interfaces.freesurfer import SampleToSurface
    from nipype.interfaces.freesurfer.preprocess import MRIConvert

    # set freesurfer path environment
    os.environ["SUBJECTS_DIR"] = path_output

    # freesurfer subject
    tmp = np.random.randint(0, 10, 5)
    tmp_string = ''.join(str(i) for i in tmp)
    sub = "tmp_" + tmp_string

    # make output folder
    if not os.path.exists(path_output):
        os.makedirs(path_output)

    # mimic freesurfer folder structure (with some additional folder for intermediate files)
    path_sub = os.path.join(path_output, sub)
    path_mri = os.path.join(path_sub, "mri")
    path_surf = os.path.join(path_sub, "surf")

    os.makedirs(path_sub)
    os.makedirs(path_mri)
    os.makedirs(path_surf)

    # copy input volume as orig.mgz to mimicked freesurfer folder
    if os.path.splitext(os.path.basename(input_vol))[1] is not ".mgz":
        mc = MRIConvert()
        mc.inputs.in_file = input_vol
        mc.inputs.out_file = os.path.join(path_mri, "orig.mgz")
        mc.inputs.out_type = 'mgz'
        mc.run()
    else:
        sh.copyfile(input_vol, os.path.join(path_mri, "orig.mgz"))

    # copy input surface to mimicked freesurfer folder
    sh.copyfile(input_surf, os.path.join(path_surf, hemi + ".source"))

    # input volume file name
    if os.path.splitext(os.path.basename(input_vol))[1] == ".gz":
        name_vol = os.path.splitext(
            os.path.splitext(os.path.basename(input_vol))[0])[0]
    else:
        name_vol = os.path.splitext(os.path.basename(input_vol))[0]
    name_surf = os.path.basename(input_surf).split('.')[1]

    # mri_vol2surf
    sampler = SampleToSurface()
    sampler.inputs.subject_id = sub
    sampler.inputs.reg_header = True
    sampler.inputs.hemi = hemi
    sampler.inputs.source_file = input_vol
    sampler.inputs.surface = "source"
    sampler.inputs.sampling_method = "point"
    sampler.inputs.sampling_range = 0
    sampler.inputs.sampling_units = "mm"
    sampler.inputs.interp_method = "nearest"  # or trilinear
    sampler.inputs.out_type = "mgh"
    sampler.inputs.out_file = os.path.join(path_surf,
                                           hemi + "." + "sampled.mgh")
    sampler.run()

    if input_ind:
        # read ind
        ind_orig = np.loadtxt(input_ind, dtype=int)

        # read white
        vtx_orig, _ = read_geometry(input_white)

        # read sampled morph data
        vals_img = nb.load(os.path.join(path_surf, hemi + "." + "sampled.mgh"))
        vals_array = vals_img.get_fdata()

        # get anzahl der vertices als Nullen in white
        vals_orig = np.zeros([len(vtx_orig[:, 0]), 1, 1])

        # setze sampled data da rein
        vals_orig[ind_orig] = vals_array

        # write sampled data in anatomical space
        vals_img.header["dims"][0] = len(vals_orig[:, 0])
        vals_img.header["Mdc"] = np.eye(3)
        res_img = nb.Nifti1Image(vals_orig, vals_img.affine, vals_img.header)
        nb.save(
            res_img,
            os.path.join(
                path_output,
                hemi + "." + name_vol + "_" + name_surf + "_def_trans.mgh"))
    else:
        # write sampled data in epi space
        sh.copyfile(
            os.path.join(path_surf, hemi + "." + "sampled.mgh"),
            os.path.join(path_output,
                         hemi + "." + name_vol + "_" + name_surf + "_def.mgh"))

    # delete intermediate files
    if cleanup:
        sh.rmtree(path_sub, ignore_errors=True)
Example #6
0
sh.copyfile(file_orig, os.path.join(path_orig, "orig.mgz"))
sh.copyfile(file_mean_epi, os.path.join(path_epi, "epi.nii"))
sh.copyfile(file_t1, os.path.join(path_t1, "T1.nii"))
"""
mask preparation
"""

# convert to nifti
if os.path.splitext(file_mask)[1] == ".mgh":
    sh.copyfile(file_mask, os.path.join(path_t1, "mask.mgh"))
    mc = MRIConvert()
    mc.inputs.in_file = os.path.join(path_t1, "mask.mgh")
    mc.inputs.out_file = os.path.join(path_t1, "mask.nii")
    mc.inputs.in_type = "mgh"
    mc.inputs.out_type = "nii"
    mc.run()
elif os.path.splitext(file_mask)[1] == ".mgz":
    sh.copyfile(file_mask, os.path.join(path_t1, "mask.mgz"))
    mc = MRIConvert()
    mc.inputs.in_file = os.path.join(path_t1, "mask.mgz")
    mc.inputs.out_file = os.path.join(path_t1, "mask.nii")
    mc.inputs.in_type = "mgz"
    mc.inputs.out_type = "nii"
    mc.run()
elif os.path.splitext(file_mask)[1] == ".gz":
    sh.copyfile(file_mask, os.path.join(path_t1, "mask.nii.gz"))
    gunzip(os.path.join(path_t1, "mask.nii.gz"))
elif os.path.splitext(file_mask)[1] == ".nii":
    sh.copyfile(file_mask, os.path.join(path_t1, "mask.nii"))
else:
    print("File extension of mask could not be identified!")