Source code for macapype.nodes.surface

from nipype.interfaces.base import TraitedSpec, SimpleInterface
from nipype.interfaces.base import traits, File


def split_LR_mask(LR_mask_file, left_index=1, right_index=2):

    import os

    import nibabel as nib
    import numpy as np

    from nipype.utils.filemanip import split_filename as split_f

    path, fname, ext = split_f(LR_mask_file)

    LR_mask_img = nib.load(LR_mask_file)

    LR_mask_data = LR_mask_img.get_fdata()

    # L_mask
    L_mask_data = np.zeros(shape=LR_mask_data.shape)

    L_mask_data[LR_mask_data == left_index] = 1

    L_mask_file = os.path.abspath("L_mask"+ext)

    nib.save(
        nib.Nifti1Image(L_mask_data, affine=LR_mask_img.affine,
                        header=LR_mask_img.header),
        L_mask_file)

    # R_mask
    R_mask_data = np.zeros(shape=LR_mask_data.shape)

    R_mask_data[LR_mask_data == right_index] = 1

    R_mask_file = os.path.abspath("R_mask"+ext)

    nib.save(
        nib.Nifti1Image(R_mask_data, affine=LR_mask_img.affine,
                        header=LR_mask_img.header),
        R_mask_file)

    return L_mask_file, R_mask_file


class MeshifyInputSpec(TraitedSpec):
    image_file = File(
        exists=True, desc='input file', mandatory=True)

    level = traits.Float(
        0.5, usedefault=True,
        desc='Threshold used to detect surfaces',
        mandatory=False)

    smoothing_iter = traits.Int(
        0, usedefault=True,
        desc='Number of Laplacian smoothing iterations',
        mandatory=False)

    smoothing_dt = traits.Float(
        0.1, usedefault=True,
        desc='dt param of the Laplacian smoothing',
        mandatory=False)


class MeshifyOutputSpec(TraitedSpec):
    mesh_file = File(desc="out file", exists=True)


[docs]class Meshify(SimpleInterface): """ Definition: Create a Gifti mesh from a binary Nifti image """ _cmd = 'fslorient' input_spec = MeshifyInputSpec output_spec = MeshifyOutputSpec def _run_interface(self, runtime): import os.path as op import nibabel.gifti as ng import numpy as np import skimage.measure as sm import nilearn.image as nimg import slam.io as sio import slam.differential_geometry as sdg from nipype.utils.filemanip import split_filename # Generate output mesh filename from the input image name _, fname, _ = split_filename(self.inputs.image_file) gii_file = op.abspath(op.join(runtime.cwd, fname + ".gii")) # Load the largest connected component of the input image img = nimg.largest_connected_component_img(self.inputs.image_file) # TODO: check if the input image is correct (binary) # Run the marching cube algorithm verts, faces, normals, values = sm.marching_cubes_lewiner( img.get_data(), self.inputs.level) # Convert vertices coordinates to image space # TODO: check that is correct by plotting the mesh on the image x, y, z = nimg.coord_transform( verts[:, 0], verts[:, 1], verts[:, 2], img.affine) mm_verts = np.array([x, y, z]).T # Save the mesh as Gifti # FIXME: FreeView can not open the mesh (but anatomist do) gii = ng.GiftiImage(darrays=[ ng.GiftiDataArray(mm_verts, intent='NIFTI_INTENT_POINTSET'), ng.GiftiDataArray(faces, intent='NIFTI_INTENT_TRIANGLE')]) gii.meta = ng.GiftiMetaData().from_dict({ "volume_file": self.inputs.image_file, "marching_cube_level": str(self.inputs.level), "smoothing_iterations": str(self.inputs.smoothing_iter), "smoothing_dt": str(self.inputs.smoothing_dt) }) ng.write(gii, gii_file) # Optional: Smooth the marching cube output with SLAM if self.inputs.smoothing_iter > 0: mesh = sdg.laplacian_mesh_smoothing( sio.load_mesh(gii_file), nb_iter=self.inputs.smoothing_iter, dt=self.inputs.smoothing_dt) sio.write_mesh(mesh, gii_file) return runtime