def checkFirst(prefix, structures): #pylint: disable=unused-variable import os from mrtrix3 import app, file, path # pylint: disable=redefined-builtin vtk_files = [ prefix + '-' + struct + '_first.vtk' for struct in structures ] existing_file_count = sum([ os.path.exists(filename) for filename in vtk_files ]) if existing_file_count != len(vtk_files): if 'SGE_ROOT' in os.environ: app.console('FSL FIRST job has been submitted to SGE; awaiting completion') app.console('(note however that FIRST may fail silently, and hence this script may hang indefinitely)') file.waitFor(vtk_files) else: app.error('FSL FIRST has failed; only ' + str(existing_file_count) + ' of ' + str(len(vtk_files)) + ' structures were segmented successfully (check ' + path.toTemp('first.logs', False) + ')')
def checkFirst(prefix, structures): #pylint: disable=unused-variable import os from mrtrix3 import app, file, path # pylint: disable=redefined-builtin vtk_files = [prefix + '-' + struct + '_first.vtk' for struct in structures] existing_file_count = sum( [os.path.exists(filename) for filename in vtk_files]) if existing_file_count != len(vtk_files): if 'SGE_ROOT' in os.environ: app.console( 'FSL FIRST job has been submitted to SGE; awaiting completion') app.console( '(note however that FIRST may fail silently, and hence this script may hang indefinitely)' ) file.waitFor(vtk_files) else: app.error('FSL FIRST has failed; only ' + str(existing_file_count) + ' of ' + str(len(vtk_files)) + ' structures were segmented successfully (check ' + path.toTemp('first.logs', False) + ')')
def execute(): import os from distutils.spawn import find_executable from mrtrix3 import app, file, fsl, image, run if app.isWindows(): app.error( '\'fsl\' algorithm of 5ttgen script cannot be run on Windows: FSL not available on Windows' ) fsl_path = os.environ.get('FSLDIR', '') if not fsl_path: app.error( 'Environment variable FSLDIR is not set; please run appropriate FSL configuration script' ) ssroi_cmd = 'standard_space_roi' if not find_executable(ssroi_cmd): ssroi_cmd = 'fsl5.0-standard_space_roi' if not find_executable(ssroi_cmd): app.error( 'Could not find FSL program standard_space_roi; please verify FSL install' ) bet_cmd = 'bet' if not find_executable(bet_cmd): bet_cmd = 'fsl5.0-bet' if not find_executable(bet_cmd): app.error( 'Could not find FSL program bet; please verify FSL install') fast_cmd = 'fast' if not find_executable(fast_cmd): fast_cmd = 'fsl5.0-fast' if not find_executable(fast_cmd): app.error( 'Could not find FSL program fast; please verify FSL install') first_cmd = 'run_first_all' if not find_executable(first_cmd): first_cmd = "fsl5.0-run_first_all" if not find_executable(first_cmd): app.error( 'Could not find FSL program run_first_all; please verify FSL install' ) first_atlas_path = os.path.join(fsl_path, 'data', 'first', 'models_336_bin') if not os.path.isdir(first_atlas_path): app.error( 'Atlases required for FSL\'s FIRST program not installed; please install fsl-first-data using your relevant package manager' ) fsl_suffix = fsl.suffix() sgm_structures = [ 'L_Accu', 'R_Accu', 'L_Caud', 'R_Caud', 'L_Pall', 'R_Pall', 'L_Puta', 'R_Puta', 'L_Thal', 'R_Thal' ] if app.args.sgm_amyg_hipp: sgm_structures.extend(['L_Amyg', 'R_Amyg', 'L_Hipp', 'R_Hipp']) run.command('mrconvert input.mif T1.nii -stride -1,+2,+3') fast_t1_input = 'T1.nii' fast_t2_input = '' # Decide whether or not we're going to do any brain masking if os.path.exists('mask.mif'): fast_t1_input = 'T1_masked' + fsl_suffix # Check to see if the mask matches the T1 image if image.match('T1.nii', 'mask.mif'): run.command('mrcalc T1.nii mask.mif -mult ' + fast_t1_input) mask_path = 'mask.mif' else: app.warn('Mask image does not match input image - re-gridding') run.command( 'mrtransform mask.mif mask_regrid.mif -template T1.nii') run.command('mrcalc T1.nii mask_regrid.mif ' + fast_t1_input) mask_path = 'mask_regrid.mif' if os.path.exists('T2.nii'): fast_t2_input = 'T2_masked' + fsl_suffix run.command('mrcalc T2.nii ' + mask_path + ' -mult ' + fast_t2_input) elif app.args.premasked: fast_t1_input = 'T1.nii' if os.path.exists('T2.nii'): fast_t2_input = 'T2.nii' else: # Use FSL command standard_space_roi to do an initial masking of the image before BET # Also reduce the FoV of the image # Using MNI 1mm dilated brain mask rather than the -b option in standard_space_roi (which uses the 2mm mask); the latter looks 'buggy' to me... Unfortunately even with the 1mm 'dilated' mask, it can still cut into some brain areas, hence the explicit dilation mni_mask_path = os.path.join(fsl_path, 'data', 'standard', 'MNI152_T1_1mm_brain_mask_dil.nii.gz') mni_mask_dilation = 0 if os.path.exists(mni_mask_path): mni_mask_dilation = 4 else: mni_mask_path = os.path.join( fsl_path, 'data', 'standard', 'MNI152_T1_2mm_brain_mask_dil.nii.gz') if os.path.exists(mni_mask_path): mni_mask_dilation = 2 if mni_mask_dilation: run.command('maskfilter ' + mni_mask_path + ' dilate mni_mask.nii -npass ' + str(mni_mask_dilation)) if app.args.nocrop: ssroi_roi_option = ' -roiNONE' else: ssroi_roi_option = ' -roiFOV' run.command( ssroi_cmd + ' T1.nii T1_preBET' + fsl_suffix + ' -maskMASK mni_mask.nii' + ssroi_roi_option, False) else: run.command(ssroi_cmd + ' T1.nii T1_preBET' + fsl_suffix + ' -b', False) # For whatever reason, the output file from standard_space_roi may not be # completed before BET is run file.waitFor('T1_preBET' + fsl_suffix) # BET fast_t1_input = 'T1_BET' + fsl_suffix run.command(bet_cmd + ' T1_preBET' + fsl_suffix + ' ' + fast_t1_input + ' -f 0.15 -R') if os.path.exists('T2.nii'): if app.args.nocrop: fast_t2_input = 'T2.nii' else: # Just a reduction of FoV, no sub-voxel interpolation going on run.command('mrtransform T2.nii T2_cropped.nii -template ' + fast_t1_input + ' -interp nearest') fast_t2_input = 'T2_cropped.nii' # Finish branching based on brain masking # FAST if fast_t2_input: run.command(fast_cmd + ' -S 2 ' + fast_t2_input + ' ' + fast_t1_input) else: run.command(fast_cmd + ' ' + fast_t1_input) fast_output_prefix = fast_t1_input.split('.')[0] # FIRST first_input_is_brain_extracted = '' if app.args.premasked: first_input_is_brain_extracted = ' -b' run.command(first_cmd + ' -s ' + ','.join(sgm_structures) + ' -i T1.nii -o first' + first_input_is_brain_extracted) # Test to see whether or not FIRST has succeeded # However if the expected image is absent, it may be due to FIRST being run # on SGE; in this case it is necessary to wait and see if the file appears. # But even in this case, FIRST may still fail, and the file will never appear... combined_image_path = 'first_all_none_firstseg' + fsl_suffix if not os.path.isfile(combined_image_path): if 'SGE_ROOT' in os.environ: app.console( 'FSL FIRST job has been submitted to SGE; awaiting completion') app.console( '(note however that FIRST may fail, and hence this script may hang indefinitely)' ) file.waitFor(combined_image_path) else: app.error( 'FSL FIRST has failed; not all structures were segmented successfully (check ' + path.toTemp('first.logs', False) + ')') # Convert FIRST meshes to partial volume images pve_image_list = [] for struct in sgm_structures: pve_image_path = 'mesh2pve_' + struct + '.mif' vtk_in_path = 'first-' + struct + '_first.vtk' vtk_temp_path = struct + '.vtk' run.command('meshconvert ' + vtk_in_path + ' ' + vtk_temp_path + ' -transform first2real T1.nii') run.command('mesh2pve ' + vtk_temp_path + ' ' + fast_t1_input + ' ' + pve_image_path) pve_image_list.append(pve_image_path) pve_cat = ' '.join(pve_image_list) run.command('mrmath ' + pve_cat + ' sum - | mrcalc - 1.0 -min all_sgms.mif') # Looks like FAST in 5.0 ignores FSLOUTPUTTYPE when writing the PVE images # Will have to wait and see whether this changes, and update the script accordingly if fast_cmd == 'fast': fast_suffix = fsl_suffix else: fast_suffix = '.nii.gz' # Combine the tissue images into the 5TT format within the script itself # Step 1: Run LCC on the WM image run.command( 'mrthreshold ' + fast_output_prefix + '_pve_2' + fast_suffix + ' - -abs 0.001 | maskfilter - connect - -connectivity | mrcalc 1 - 1 -gt -sub remove_unconnected_wm_mask.mif -datatype bit' ) # Step 2: Generate the images in the same fashion as the 5ttgen command run.command('mrcalc ' + fast_output_prefix + '_pve_0' + fast_suffix + ' remove_unconnected_wm_mask.mif -mult csf.mif') run.command('mrcalc 1.0 csf.mif -sub all_sgms.mif -min sgm.mif') run.command('mrcalc 1.0 csf.mif sgm.mif -add -sub ' + fast_output_prefix + '_pve_1' + fast_suffix + ' ' + fast_output_prefix + '_pve_2' + fast_suffix + ' -add -div multiplier.mif') run.command( 'mrcalc multiplier.mif -finite multiplier.mif 0.0 -if multiplier_noNAN.mif' ) run.command( 'mrcalc ' + fast_output_prefix + '_pve_1' + fast_suffix + ' multiplier_noNAN.mif -mult remove_unconnected_wm_mask.mif -mult cgm.mif' ) run.command( 'mrcalc ' + fast_output_prefix + '_pve_2' + fast_suffix + ' multiplier_noNAN.mif -mult remove_unconnected_wm_mask.mif -mult wm.mif' ) run.command('mrcalc 0 wm.mif -min path.mif') run.command( 'mrcat cgm.mif sgm.mif wm.mif csf.mif path.mif - -axis 3 | mrconvert - combined_precrop.mif -stride +2,+3,+4,+1' ) # Use mrcrop to reduce file size (improves caching of image data during tracking) if app.args.nocrop: run.command('mrconvert combined_precrop.mif result.mif') else: run.command( 'mrmath combined_precrop.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrcrop combined_precrop.mif result.mif -mask -' )