예제 #1
0
def require_brain_mask(config,
                       section,
                       config_vars,
                       stack,
                       verbose=0,
                       keep_regions_mask=False):
    """Resample input brain mask to standard RAS space."""
    brain_mask = config.get(section, 'brain_mask', vars=config_vars)
    if os.path.isfile(brain_mask):
        return brain_mask
    require_input_brain_mask(config, section, config_vars, stack, verbose)
    if keep_regions_mask:
        require_regions_mask(config, section, config_vars, None, verbose)
    else:
        require_regions_mask(config, section, config_vars, stack, verbose)
    if verbose > 0:
        print("Resampling brain mask to standard RAS space")
    neoctx.binarize(name=brain_mask,
                    segmentation=config.get(section,
                                            'input_brain_mask',
                                            vars=config_vars),
                    image=config.get(section, 'regions_mask',
                                     vars=config_vars),
                    threshold=0,
                    temp=config.get(section, 'temp_dir', vars=config_vars))
    if stack:
        brain_mask = neoctx.push_output(stack, brain_mask)
    neoctx.run('close-image',
               args=[brain_mask, brain_mask],
               opts={'iterations': 5})
    return brain_mask
예제 #2
0
def recon_neonatal_cortex(config,
                          section,
                          config_vars,
                          with_brain_mesh=False,
                          with_bs_cb_mesh=True,
                          with_cerebrum_mesh=False,
                          with_white_mesh=True,
                          with_pial_mesh=True,
                          keep_t1w_image=False,
                          keep_t2w_image=False,
                          keep_regions_mask=False,
                          pial_outside_white_surface=False,
                          join_internal_mesh=False,
                          join_bs_cb_mesh=False,
                          cut=True,
                          force=False,
                          check=True,
                          verbose=0):
    """Reconstruct surfaces of neonatal cortex."""

    # working directory
    temp_dir = config.get(section, 'temp_dir', vars=config_vars)

    # intermediate image files in standard RAS space
    t1w_image = config.get(section, 't1w_image', vars=config_vars)
    t2w_image = config.get(section, 't2w_image', vars=config_vars)
    brain_mask = config.get(section, 'brain_mask', vars=config_vars)
    wm_mask = config.get(section, 'white_matter_mask', vars=config_vars)
    gm_mask = config.get(section, 'gray_matter_mask', vars=config_vars)
    deep_gray_matter_mask = config.get(section,
                                       'deep_gray_matter_mask',
                                       vars=config_vars)
    regions_mask = config.get(section, 'regions_mask', vars=config_vars)
    cortical_hull_dmap = config.get(section,
                                    'cortical_hull_dmap',
                                    vars=config_vars)
    ventricles_dmap = config.get(section, 'ventricles_dmap', vars=config_vars)

    # output mesh files
    brain_mesh = config.get(section, 'brain_mesh', vars=config_vars)
    bs_cb_mesh = config.get(section, 'bs_cb_mesh', vars=config_vars)
    internal_mesh = config.get(section, 'internal_mesh', vars=config_vars)
    cerebrum_mesh = config.get(section, 'cerebrum_mesh', vars=config_vars)
    right_cerebrum_mesh = config.get(section,
                                     'right_cerebrum_mesh',
                                     vars=config_vars)
    left_cerebrum_mesh = config.get(section,
                                    'left_cerebrum_mesh',
                                    vars=config_vars)
    white_mesh = config.get(section, 'white_mesh', vars=config_vars)
    right_white_mesh = config.get(section,
                                  'right_white_mesh',
                                  vars=config_vars)
    left_white_mesh = config.get(section, 'left_white_mesh', vars=config_vars)
    pial_mesh = config.get(section, 'pial_mesh', vars=config_vars)
    right_pial_mesh = config.get(section, 'right_pial_mesh', vars=config_vars)
    left_pial_mesh = config.get(section, 'left_pial_mesh', vars=config_vars)

    internal_base = os.path.splitext(os.path.basename(internal_mesh))[0]

    if not with_brain_mesh:
        brain_mesh = None
    if not with_bs_cb_mesh:
        bs_cb_mesh = None
    if not with_pial_mesh:
        pial_mesh = None

    if bs_cb_mesh and join_bs_cb_mesh:
        bs_cb_mesh_1 = bs_cb_mesh
        bs_cb_mesh_2 = None
    else:
        bs_cb_mesh_1 = None
        bs_cb_mesh_2 = bs_cb_mesh

    # remove intermediate files that did not exist before upon exit
    with ExitStack() as stack:

        recon_pial = with_pial_mesh and (force
                                         or not os.path.isfile(pial_mesh))
        recon_white = (with_white_mesh
                       or recon_pial) and (force
                                           or not os.path.isfile(white_mesh))
        recon_cerebrum = (with_cerebrum_mesh or recon_white) and (
            force or not os.path.isfile(cerebrum_mesh))
        recon_brain = with_brain_mesh and (force
                                           or not os.path.isfile(brain_mesh))
        recon_bs_cb_mesh = ((with_bs_cb_mesh or
                             (recon_cerebrum and bs_cb_mesh_1) or
                             (recon_white and bs_cb_mesh_2))
                            and (force or not os.path.isfile(bs_cb_mesh)))

        # the surface reconstruction relies on a resampling of the intensity
        # images to the standard RAS space defined by the regions_mask / brain_mask
        if recon_brain or recon_bs_cb_mesh or recon_cerebrum or recon_white or recon_pial:
            require_brain_mask(config,
                               section,
                               config_vars,
                               stack,
                               verbose,
                               keep_regions_mask=keep_regions_mask)
        elif keep_regions_mask:
            # create regions mask only, skip surface reconstruction
            require_regions_mask(config, section, config_vars, None, verbose)

        if recon_white or recon_pial:
            if not os.path.isfile(t2w_image):
                input_t2w_image = config.get(section,
                                             'input_t2w_image',
                                             vars=config_vars)
                if os.path.isfile(input_t2w_image):
                    if verbose > 0:
                        print(
                            "Resampling T2-weighted image to standard RAS space"
                        )
                    neoctx.makedirs(t2w_image)
                    neoctx.run('transform-image',
                               args=[input_t2w_image, t2w_image],
                               opts={
                                   'interp': 'fast cubic bspline with padding',
                                   'Sp': 0,
                                   'dofin': 'Id',
                                   'target': brain_mask,
                                   'type': 'float'
                               })
                    if keep_t2w_image:
                        neoctx.push_output(stack, t2w_image)
                else:
                    raise Exception("Input T2-weighted image required")

            if not os.path.isfile(t1w_image):
                input_t1w_image = config.get(section,
                                             'input_t1w_image',
                                             vars=config_vars)
                if os.path.isfile(input_t1w_image):
                    if verbose > 0:
                        print(
                            "Resampling T1-weighted image to standard RAS space"
                        )
                    neoctx.makedirs(t1w_image)
                    neoctx.run('transform-image',
                               args=[input_t1w_image, t1w_image],
                               opts={
                                   'interp': 'fast cubic bspline with padding',
                                   'Sp': 0,
                                   'dofin': 'Id',
                                   'target': brain_mask,
                                   'type': 'float'
                               })
                    if not keep_t1w_image:
                        neoctx.push_output(stack, t1w_image)
                else:
                    if verbose > 0:
                        print(
                            "No input T1-weighted image found, using only T2-weighted image"
                        )
                    t1w_image = None

        # reconstruct boundary of brain mask
        if recon_brain:
            if verbose > 0:
                print("Reconstructing boundary of brain mask")
            neoctx.recon_brain_surface(name=brain_mesh,
                                       mask=brain_mask,
                                       temp=temp_dir)

        # reconstruct brainstem plus cerebellum surface
        if recon_bs_cb_mesh:
            if verbose > 0:
                print("Reconstructing brainstem plus cerebellum surface")
            neoctx.recon_brainstem_plus_cerebellum_surface(
                name=bs_cb_mesh, regions=regions_mask, temp=temp_dir)

        # reconstruct inner-cortical surface from segmentation
        if recon_cerebrum:

            # at the moment already ensured by require_brain_mask above...
            if keep_regions_mask:
                require_regions_mask(config, section, config_vars, None,
                                     verbose)
            else:
                require_regions_mask(config, section, config_vars, stack,
                                     verbose)

            # reconstruct inner-cortical surfaces of right and left hemispheres
            if force or not os.path.isfile(right_cerebrum_mesh):
                corpus_callosum_mask = optional_corpus_callosum_mask(
                    config, section, config_vars, stack, verbose)
                if verbose > 0:
                    print(
                        "Reconstructing boundary of right cerebral hemisphere segmentation"
                    )
                neoctx.recon_cortical_surface(
                    name=right_cerebrum_mesh,
                    regions=regions_mask,
                    hemisphere=neoctx.Hemisphere.Right,
                    corpus_callosum_mask=corpus_callosum_mask,
                    temp=temp_dir)
            if force or not os.path.isfile(left_cerebrum_mesh):
                corpus_callosum_mask = optional_corpus_callosum_mask(
                    config, section, config_vars, stack, verbose)
                if verbose > 0:
                    print(
                        "Reconstructing boundary of left cerebral hemisphere segmentation"
                    )
                neoctx.recon_cortical_surface(
                    name=left_cerebrum_mesh,
                    regions=regions_mask,
                    hemisphere=neoctx.Hemisphere.Left,
                    corpus_callosum_mask=corpus_callosum_mask,
                    temp=temp_dir)

            # join cortical surfaces of right and left hemispheres
            if verbose > 0:
                print(
                    "Joining surfaces of right and left cerebral hemispheres")
            neoctx.join_cortical_surfaces(name=cerebrum_mesh,
                                          regions=regions_mask,
                                          right_mesh=right_cerebrum_mesh,
                                          left_mesh=left_cerebrum_mesh,
                                          bs_cb_mesh=bs_cb_mesh_1,
                                          internal_mesh=internal_mesh,
                                          temp=temp_dir,
                                          check=check)

            # remove cortical surfaces of right and left hemispheres
            if not with_cerebrum_mesh:
                os.remove(right_cerebrum_mesh)
                os.remove(left_cerebrum_mesh)

        # insert internal mesh into into initial inner-cortical surface
        if with_cerebrum_mesh and join_internal_mesh:
            cerebrum_prefix, cerebrum_ext = os.path.splitext(cerebrum_mesh)
            cerebrum_plus_internal_mesh = cerebrum_prefix + '+' + internal_base + cerebrum_ext
            if force or not os.path.isfile(cerebrum_plus_internal_mesh):
                if verbose > 0:
                    print("Merging initial surface with internal mesh")
                neoctx.append_surfaces(cerebrum_plus_internal_mesh,
                                       surfaces=[cerebrum_mesh, internal_mesh],
                                       merge=True,
                                       tol=0)

        # reconstruct inner-cortical surface
        if recon_white:

            require_white_matter_mask(config, section, config_vars, stack,
                                      verbose)
            require_gray_matter_mask(config, section, config_vars, stack,
                                     verbose)
            require_deep_gray_matter_mask(config, section, config_vars, stack,
                                          verbose)
            require_ventricles_dmap(config, section, config_vars, stack,
                                    verbose)
            require_cortical_hull_dmap(config, section, config_vars, stack,
                                       verbose)

            if verbose > 0:
                print("Reconstructing inner-cortical surface")
            neoctx.recon_white_surface(name=white_mesh,
                                       t1w_image=t1w_image,
                                       t2w_image=t2w_image,
                                       wm_mask=wm_mask,
                                       gm_mask=gm_mask,
                                       cortex_mesh=cerebrum_mesh,
                                       bs_cb_mesh=bs_cb_mesh_2,
                                       subcortex_mask=deep_gray_matter_mask,
                                       cortical_hull_dmap=cortical_hull_dmap,
                                       ventricles_dmap=ventricles_dmap,
                                       temp=temp_dir,
                                       check=check)

            # remove initial surface mesh
            if not with_cerebrum_mesh:
                os.remove(cerebrum_mesh)

        # insert internal mesh and cut surface at medial plane
        split_white = (cut and (force or not os.path.isfile(right_white_mesh)
                                or not os.path.isfile(left_white_mesh)))
        white_prefix, white_ext = os.path.splitext(white_mesh)
        white_plus_internal_mesh = white_prefix + '+' + internal_base + white_ext
        if (split_white or join_internal_mesh) and (
                force or not os.path.isfile(white_plus_internal_mesh)):
            if verbose > 0:
                print("Merging inner-cortical surface with internal mesh")
            neoctx.append_surfaces(white_plus_internal_mesh,
                                   surfaces=[white_mesh, internal_mesh],
                                   merge=True,
                                   tol=0)
            if not join_internal_mesh:
                neoctx.push_output(stack, white_plus_internal_mesh)
        if split_white:
            if verbose > 0:
                print("Cutting inner-cortical surface at medial cutting plane")
            neoctx.split_cortical_surfaces(
                joined_mesh=white_plus_internal_mesh,
                right_name=right_white_mesh,
                left_name=left_white_mesh,
                temp=temp_dir)

        # reconstruct outer-cortical surface
        if recon_pial:

            require_white_matter_mask(config, section, config_vars, stack,
                                      verbose)
            require_gray_matter_mask(config, section, config_vars, stack,
                                     verbose)

            if verbose > 0:
                print("Reconstructing outer-cortical surface")
            neoctx.recon_pial_surface(
                name=pial_mesh,
                t2w_image=t2w_image,
                wm_mask=wm_mask,
                gm_mask=gm_mask,
                brain_mask=brain_mask,
                white_mesh=white_mesh,
                bs_cb_mesh=bs_cb_mesh_2,
                outside_white_mesh=pial_outside_white_surface,
                temp=temp_dir,
                check=check)

            # remove inner-cortical surface
            if not with_white_mesh:
                os.remove(white_mesh)

        # insert internal mesh and cut surface at medial plane
        if with_pial_mesh:
            split_pial = (cut and (force or not os.path.isfile(right_pial_mesh)
                                   or not os.path.isfile(left_pial_mesh)))
            pial_prefix, pial_ext = os.path.splitext(pial_mesh)
            pial_plus_internal_mesh = pial_prefix + '+' + internal_base + pial_ext
            if (split_pial or join_internal_mesh) and (
                    force or not os.path.isfile(pial_plus_internal_mesh)):
                if verbose > 0:
                    print("Merging pial surface with internal mesh")
                neoctx.append_surfaces(pial_plus_internal_mesh,
                                       surfaces=[pial_mesh, internal_mesh],
                                       merge=True,
                                       tol=0)
                if not join_internal_mesh:
                    neoctx.push_output(stack, pial_plus_internal_mesh)
            if split_pial:
                if verbose > 0:
                    print(
                        "Cutting outer-cortical surface at medial cutting plane"
                    )
                neoctx.split_cortical_surfaces(
                    joined_mesh=pial_plus_internal_mesh,
                    right_name=right_pial_mesh,
                    left_name=left_pial_mesh,
                    temp=temp_dir)