Ejemplo n.º 1
0
def mesh_sampling_layer(surf_in,
                        file_in,
                        boundaries_in,
                        path_output,
                        layer,
                        r=[0.4, 0.4, 0.4],
                        interpolation="Cu",
                        average_layer=False,
                        write_profile=True,
                        write_upsampled=True):
    """
    This function samples data from an image volume to a surface mesh from specific layers defined 
    by a levelset image. If average_layer is true, the parameter layer should contain only two 
    integers which denote the start and ending layer.
    Inputs:
        *surf_in: filename of input surface mesh.
        *file_in: filename of input volume from which data is sampled.
        *boundaries_in: filename of 4D levelset image.
        *path_output: path where output is written.
        *layer: which layers to sample (array of integers).
        *r: destination voxel size after upsampling (performed if not None).
        *interpolation: interpolation method for upsampling of file from whic data is sampled.
        *average_layer: average across cortex.
        *write_profile: write sampled profile.
        *write_upsampled: write upsampled file.
    
    created by Daniel Haenelt
    Date created: 18-12-2019
    Last modified: 24-07-2020
    """
    import os
    import sys
    import shutil as sh
    import numpy as np
    import nibabel as nb
    from os.path import join, exists, basename, splitext
    from nighres.laminar import profile_sampling
    from lib.io.get_filename import get_filename
    from lib.utils.upsample_volume import upsample_volume
    from lib.mapping import map2surface

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

    # filenames
    _, name_file, ext_file = get_filename(file_in)
    _, hemi, name_surf = get_filename(surf_in)

    name_surf = name_surf[1:]
    name_profile = splitext(basename(file_in))[0] + "_profile"

    # check hemi
    if not hemi == "lh" and not hemi == "rh":
        sys.exit("Could not identify hemi from filename!")

    # upsample volume
    if not r == None:
        name_file = name_file + "_upsampled"
        upsample_volume(file_in, join(path_output, name_file + ext_file), r,
                        interpolation)
    else:
        if file_in != join(path_output, name_file + ext_file):
            sh.copyfile(file_in, join(path_output, name_file + ext_file))

    # get profile sampling
    tmp = np.random.randint(0, 10, 5)
    tmp_string = ''.join(str(i) for i in tmp)
    profile = profile_sampling(boundaries_in,
                               join(path_output, name_file + ext_file),
                               save_data=write_profile,
                               overwrite=write_profile,
                               output_dir=path_output,
                               file_name="profile_" + tmp_string)

    # rename profile sampling output
    if write_profile:
        os.rename(
            join(path_output, "profile_" + tmp_string + "_lps-data.nii.gz"),
            join(path_output, name_profile + ".nii.gz"))

    # load profile
    if write_profile:
        data = nb.load(join(path_output, name_profile + ".nii.gz"))
    else:
        data = profile["result"]
    data.header["dim"][0] = 3

    # do mapping
    tmp2 = np.random.randint(0, 10, 5)
    tmp2_string = ''.join(str(i) for i in tmp2)
    if not average_layer:

        for i in range(len(layer)):
            data_array = data.get_fdata()[:, :, :, layer[i]]
            out = nb.Nifti1Image(data_array, data.affine, data.header)
            nb.save(out, join(path_output, "temp_" + tmp2_string + ".nii"))

            # do the mapping
            map2surface(surf_in,
                        join(path_output, "temp_" + tmp2_string + ".nii"),
                        hemi,
                        path_output,
                        input_white=None,
                        input_ind=None,
                        cleanup=True)

            # rename mapping file
            os.rename(
                join(
                    path_output, hemi + ".temp_" + tmp2_string + "_" +
                    name_surf + "_def.mgh"),
                join(
                    path_output, hemi + "." + name_file + "_layer" +
                    str(layer[i]) + ".mgh"))

    else:

        if len(layer) != 2:
            sys.exit("For averaging, layer should only contain two elements!")

        data_array = data.get_fdata()[:, :, :, layer[0]:layer[1]]
        data_array = np.mean(data_array, axis=3)
        out = nb.Nifti1Image(data_array, data.affine, data.header)
        nb.save(out, join(path_output, "temp_" + tmp2_string + ".nii"))

        # do the mapping
        map2surface(surf_in,
                    join(path_output, "temp_" + tmp2_string + ".nii"),
                    hemi,
                    path_output,
                    input_white=None,
                    input_ind=None,
                    cleanup=True)

        # rename mapping file
        os.rename(
            join(path_output,
                 hemi + ".temp_" + tmp2_string + "_" + name_surf + "_def.mgh"),
            join(
                path_output, hemi + "." + name_file + "_avg_layer" +
                str(layer[0]) + "_" + str(layer[1]) + ".mgh"))

    # clean temp
    os.remove(join(path_output, "temp_" + tmp2_string + ".nii"))

    # clean file
    if not write_upsampled:
        os.remove(join(path_output, name_file + ext_file))
Ejemplo n.º 2
0
    output = nb.Nifti1Image(data_array[:,:,:,i], data.affine, data.header)
    nb.save(output, os.path.join(path_native,str(i+1)+".nii")) 

# apply deformation    
for i in range(np.shape(data_array)[3]):
    apply_coordinate_mappings(os.path.join(path_native,str(i+1)+".nii"), 
                              input_deformation, 
                              interpolation=interpolation, 
                              padding='closest', 
                              save_data=True, 
                              overwrite=True, 
                              output_dir=path_def,
                              file_name=None,
                              )

# map to ana
for i in range(np.shape(data_array)[3]):
    for j in range(len(input_surf)):
        
        # hemisphere
        hemi = os.path.splitext(os.path.basename(input_surf[j]))[0]
    
        # sample on surface
        map2surface(input_surf[j], 
                    os.path.join(path_def,str(i+1)+"_def-img.nii.gz"), 
                    hemi, 
                    path_surf, 
                    input_white=None, 
                    input_ind=None, 
                    cleanup=True)
Ejemplo n.º 3
0
                               deformation_in1,
                               deformation_in2, 
                               interpolation=interpolation, 
                               padding='closest', 
                               save_data=True, 
                               overwrite=True, 
                               output_dir=path_def,
                               file_name=None,
                               )
 
 # get filename of deformed file
 if deformation_in1 is not None:
     _, name_file, _ = get_filename(file_in[i])
     filename_def = os.path.join(path_def, name_file+"_def-img.nii") 
 else:
     filename_def = file_in[i]
     
 # map to ana
 for j in range(len(surf_in)):
     
     # hemisphere
     hemi = os.path.splitext(os.path.basename(surf_in[j]))[0]
 
     # sample on surface
     map2surface(surf_in[j], 
                 filename_def, 
                 hemi, 
                 path_surf, 
                 input_white=None, 
                 input_ind=None, 
                 cleanup=True)
Ejemplo n.º 4
0
def mesh_sampling(surf_in, vol_in, source2target_in, path_output, r=[0.4,0.4,0.4], 
                  interpolation="Cu", cleanup=True):
    """
    This function samples data onto a surface mesh. Optionally, the volume can be upsampled and a
    coordinate mapping can be applied to transform the surface mesh to the space of the input 
    volume.
    Inputs:
        *surf_in: filename of input surface mesh.
        *vol_in: filename of input volume from which data is sampled.
        *source2target_in: source to target coordinate mapping.
        *path_output: path where output is written.
        *r: destination voxel size after upsampling (performed if not None).
        *interpolation: interpolation method for upsampling of file from which data is sampled.
        *cleanup: remove intermediate files.
       
    created by Daniel Haenelt
    Date created: 24-06-2020        
    Last modified: 24-06-2020
    """
    import os
    import numpy as np
    import nibabel as nb
    import shutil as sh
    from sh import gunzip
    from lib.io.get_filename import get_filename
    from lib.utils.upsample_volume import upsample_volume
    from lib.surface.deform_surface import deform_surface
    from lib.mapping import map2surface

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

    tmp = np.random.randint(0, 10, 5)
    tmp_string = ''.join(str(i) for i in tmp)
    path_temp = os.path.join(path_output, "temp_"+tmp_string)
    if not os.path.exists(path_temp):
        os.makedirs(path_temp)

    # get filenames
    _, hemi, name_mesh = get_filename(surf_in)
    name_mesh = name_mesh[1:]
    _, name_vol, _ = get_filename(vol_in)

    # set filenames
    vol_upsampled = os.path.join(path_temp, "vol_upsampled.nii")
    s2t_upsampled = os.path.join(path_temp, "s2t_upsampled.nii")

    # upsample volumes and rescale cmap
    if r:
        upsample_volume(vol_in, vol_upsampled, dxyz=r, rmode=interpolation)
        upsample_volume(source2target_in, s2t_upsampled, dxyz=r, rmode="Linear")
        
        # rescale cmap
        dim = nb.load(vol_in).header["dim"][1:4] - 1
        dim_upsampled = nb.load(vol_upsampled).header["dim"][1:4] - 1
    
        cmap_s2t = nb.load(s2t_upsampled)
        cmap_s2t_array = cmap_s2t.get_fdata()    
        for i in range(3):
            cmap_s2t_array[:,:,:,i] = cmap_s2t_array[:,:,:,i] / dim[i] * dim_upsampled[i]
        
        cmap_s2t_upsampled = nb.Nifti1Image(cmap_s2t_array, cmap_s2t.affine, cmap_s2t.header)
        nb.save(cmap_s2t_upsampled, s2t_upsampled)
    else:
        _, _, ext = get_filename(vol_in)
        sh.copy(vol_in, os.path.join(path_temp, "vol_upsampled"+ext))
        if ext[-3:] == ".gz":
            gunzip(os.path.join(path_temp, "vol_upsampled"+ext))
            
        _, _, ext = get_filename(source2target_in)
        sh.copy(source2target_in, os.path.join(path_temp, "s2t_upsampled"+ext))
        if ext[-3:] == ".gz":
            gunzip(os.path.join(path_temp, "s2t_upsampled"+ext))
        
    # deform mesh
    deform_surface(input_surf=surf_in,
                   input_orig=s2t_upsampled,
                   input_deform=s2t_upsampled,
                   input_target=vol_upsampled,
                   hemi=hemi,
                   path_output=path_temp,
                   input_mask=None,
                   interp_method="trilinear",
                   smooth_iter=0,
                   flip_faces=False,
                   cleanup=True)
    
    # do mapping
    map2surface(input_surf=os.path.join(path_temp, hemi+"."+name_mesh+"_def"),
                input_vol=vol_upsampled,
                hemi=hemi, 
                path_output=path_temp,
                input_white=None, 
                input_ind=None, 
                cleanup=True)
    
    # rename output surface
    os.rename(os.path.join(path_temp, hemi+".vol_upsampled_"+name_mesh+"_def_def.mgh"),
              os.path.join(path_output, hemi+"."+name_vol+"_"+name_mesh+".mgh"))
    
    # delete intermediate files
    if cleanup:
        sh.rmtree(path_temp, ignore_errors=True)