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
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)