Source code for cmind.pipeline.cmind_brain_extract

#!/usr/bin/env python
from __future__ import division, print_function, absolute_import

def _gen_brain_overlay_img(output_dir, head_vol, brain_vol, brain_mask_vol, verbose=False, logger=None):
    """make transparent overlay of the brain mask onto the bias-corrected head volume"""
    from os.path import join as pjoin
    from cmind.utils.logging_utils import log_cmd    
    output_img = brain_vol + '.png'
    overlay_vol = pjoin(output_dir,'overlay_tmp')
    overlay_img = output_img.replace('.png','_overlay.png')
    log_cmd('$FSLDIR/bin/slicer %s -a %s' % (brain_vol, output_img), 
                                                verbose=verbose, logger=logger)
    log_cmd('$FSLDIR/bin/overlay 1 0 %s -a %s 0.1 1 %s' % (head_vol, brain_mask_vol, overlay_vol),
                                                verbose=verbose, logger=logger)
    log_cmd('$FSLDIR/bin/slicer %s -a %s' % (overlay_vol, overlay_img), 
                                                verbose=verbose, logger=logger)
    log_cmd('$FSLDIR/bin/imrm %s' % overlay_vol, verbose=verbose, logger=logger)

[docs]def cmind_brain_extract(fname_bias, bet_thresh=0.4, brain_vol=None,extra_AFNI_args="",oname_root='T1W', generate_figures=False, ForceUpdate=False, verbose=False, logger=None, use_AFNI=False): """ Brain extraction using FSL's BET Parameters ---------- fname_bias : str input head volume bet_thresh : float, optional bet brain extraction threshold brain_vol : str, optional output volume (default is to append _brain to the input volume name) extra_AFNI_args : str, optional string of extra arguments to pass on to AFNI (e.g. "-use_skull") oname_root : str, optional output image filename prefix generate_figures : bool, optional if true, generate additional summary images ForceUpdate : bool, optional if True, rerun and overwrite any previously existing results verbose : bool, optional print additional output (to terminal and log) logger : logging.Logger or str, optional logging.Logger object (or string of a filename to log to) use_AFNI : bool, optional if True use AFNI's 3dSkullStrip instead of BET Returns ------- brain_vol : str Bias corrected + brain extracted brain_mask : str brain mask Notes ----- .. figure:: ../img/T1W_N4.png :align: center T1-weighted head prior to brain extraction .. figure:: ../img/T1W_N4_brain.png :align: center T1-weighted head after brain extraction .. figure:: ../img/brain_mask_overlay.png :align: center brain mask overlay """ import os from cmind.utils.utils import input2bool from cmind.utils.file_utils import imexist, split_multiple_ext from cmind.utils.logging_utils import cmind_init_logging, log_cmd, cmind_func_info from cmind.pipeline.cmind_brain_extract import _gen_brain_overlay_img #convert various strings to boolean generate_figures, ForceUpdate, verbose, use_AFNI = input2bool([generate_figures, ForceUpdate, verbose, use_AFNI]) if verbose: cmind_func_info(logger=logger) module_logger=cmind_init_logging(verbose=verbose, logger=logger) module_logger.info("Starting Brain Extraction") (imbool, fname_bias, fname_bias_root,output_dir, fname_bias_ext)=imexist(fname_bias,'nifti-1') if not imbool: raise IOError("input image, %s, doesn't exist!" % fname_bias) bias_vol = os.path.join(output_dir,fname_bias_root) if not brain_vol or os.path.isdir(brain_vol): #default output filenames if not brain_vol: #make a default filename based on fname_bias brain_vol = os.path.join(output_dir,fname_bias_root+'_brain') else: #make a default filename in the specified directory output_dir=brain_vol brain_vol = os.path.join(brain_vol, fname_bias_root+'_brain') # ##modify default filenames, based on input parameters #if use_AFNI: # brain_vol=brain_vol.replace('_brain','_AFNI_brain') #else: # brain_vol=brain_vol.replace('_brain','_BET_thresh%03d_brain' % int(round(100*bet_thresh))) # brain_vol=split_multiple_ext(brain_vol)[0] #strip extensions brain_mask = brain_vol+'_mask' (imbool,brain_vol_full)=imexist(brain_vol,'nifti-1')[0:2] if (not imbool) or ForceUpdate: if use_AFNI==True: from cmind.globals import cmind_AFNI_dir if imbool: #have to remove old .nii.gz to avoid having duplicate .nii and .nii.gz at same time log_cmd('$FSLDIR/bin/imrm %s' % brain_vol, verbose=verbose, logger=logger) #log_cmd('%s/3dSkullStrip -input %s.nii.gz -prefix %s -orig_vol -ld 30' % (cmind_AFNI_dir,bias_vol,brain_vol), verbose=verbose, logger=module_logger) log_cmd('%s/3dSkullStrip -input %s -prefix %s -orig_vol %s' % (cmind_AFNI_dir,bias_vol+fname_bias_ext,brain_vol, extra_AFNI_args), verbose=verbose, logger=module_logger) log_cmd('%s/3dAFNItoNIFTI -prefix %s %s' % (cmind_AFNI_dir,brain_vol,brain_vol+'+orig.BRIK'), verbose=verbose, logger=module_logger) log_cmd('$FSLDIR/bin/fslchfiletype NIFTI_GZ %s' % (brain_vol), verbose=verbose, logger=module_logger) os.remove(brain_vol+'+orig.BRIK') os.remove(brain_vol+'+orig.HEAD') if os.path.exists('skull_strip_out_hull.ply'): #remove .ply file that may have been created in the current folder if the -use_skull option was specified os.remove('skull_strip_out_hull.ply') else: log_cmd('$FSLDIR/bin/bet %s %s -f %f -g 0 -R' % (bias_vol, brain_vol, bet_thresh), verbose=verbose, logger=module_logger) log_cmd('$FSLDIR/bin/fslmaths %s -thr 0 -bin %s' % (brain_vol, brain_mask), verbose=verbose, logger=module_logger) if not oname_root: oname_root='T1W' if generate_figures: _gen_brain_overlay_img(output_dir,bias_vol,brain_vol,brain_mask, verbose=verbose, logger=module_logger) else: module_logger.info("Brain Extraction previously performed...skipping") #make sure filenames returned have the full path and extensions (imbool,brain_vol)=imexist(brain_vol,'nifti-1')[0:2] (imbool,brain_mask)=imexist(brain_mask,'nifti-1')[0:2] return (brain_vol,brain_mask)
def _testme(): import os, tempfile from cmind.utils.logging_utils import cmind_logger from cmind.globals import cmind_example_output_dir bet_thresh=0.4 oname_root='T1W' generate_figures=True ForceUpdate=True verbose=True logger=cmind_logger(log_level_console='INFO',logfile=os.path.join(tempfile.gettempdir(),'cmind_log.txt'),log_level_file='DEBUG',file_mode='w') if verbose: func=cmind_timer(cmind_brain_extract,logger=logger) else: func=cmind_brain_extract testcases=['P','F'] for testcase in testcases: fname_bias=os.path.join(cmind_example_output_dir,testcase,'T1_proc','T1W_Structural_N4.nii.gz') brain_vol=os.path.join(cmind_example_output_dir,testcase,'T1_proc','T1W_Structural_N4_brain.nii.gz') for use_AFNI in [False, True]: if use_AFNI: oname_root='T1W_AFNI' extra_AFNI_args='-use_skull' brain_vol=brain_vol.replace('N4_brain','N4_AFNI_brain') else: oname_root='T1W' extra_AFNI_args="" func(fname_bias, bet_thresh=bet_thresh, extra_AFNI_args=extra_AFNI_args, brain_vol=brain_vol, oname_root=oname_root, generate_figures=generate_figures, ForceUpdate=ForceUpdate, verbose=verbose, logger=logger, use_AFNI=use_AFNI) if __name__ == '__main__': import sys, argparse from cmind.utils.utils import str2none, _parser_to_loni from cmind.utils.decorators import cmind_timer if len(sys.argv) == 2 and sys.argv[1]=='test': _testme() else: parser = argparse.ArgumentParser(description="Brain extraction using FSL's BET", epilog="") #-h, --help exist by default #example of a positional argument parser.add_argument("fname_bias", help="input head volume") parser.add_argument("--bet_thresh",type=float,default=0.3, help="bet brain extraction threshold") parser.add_argument("--oname_root",type=str,default="T1W", help="output image filename prefix") parser.add_argument("--brain_vol",type=str,default="none", help="output volume (default is to append _brain to the input volume name)") parser.add_argument("--extra_AFNI_args",type=str,default="", help="string of extra arguments to pass on to AFNI (e.g. 'use_skull')") parser.add_argument("--use_AFNI",type=str,default="False", help="if True use AFNI's 3dSkullStrip instead of BET") parser.add_argument("-gf","--generate_figures",type=str,default="True", help="if true, generate additional summary images") parser.add_argument("-u","--ForceUpdate",type=str,default="False", help="if True, rerun and overwrite any previously existing results") parser.add_argument("-v","-debug","--verbose", help="print additional output (to terminal and log)", action="store_true") parser.add_argument("-log","--logfile", dest='logger', type=str, default="", help="logging.Logger object (or string of a filename to log to)") #if first command line argument is 'loni_bash', print bash template instead of proceeding _parser_to_loni(parser, sys.argv, __file__) #kludge to auto-generate case/esac and usage statements for the corresponding LONI shell scripts args=parser.parse_args() fname_bias=args.fname_bias; bet_thresh=args.bet_thresh; oname_root=args.oname_root; brain_vol=str2none(args.brain_vol) #If None, will use default name extra_AFNI_args=args.extra_AFNI_args generate_figures=args.generate_figures; ForceUpdate=args.ForceUpdate; verbose=args.verbose; logger=args.logger use_AFNI=args.use_AFNI if verbose: cmind_brain_extract=cmind_timer(cmind_brain_extract,logger=logger) cmind_brain_extract(fname_bias, bet_thresh=bet_thresh, extra_AFNI_args=extra_AFNI_args, brain_vol=brain_vol, oname_root=oname_root, generate_figures=generate_figures, ForceUpdate=ForceUpdate, verbose=verbose, logger=logger, use_AFNI=use_AFNI)