def execute(): #pylint: disable=unused-variable from mrtrix3 import app, path, run grad_option = '' if app.ARGS.grad: grad_option = ' -grad ' + path.from_user(app.ARGS.grad) elif app.ARGS.fslgrad: grad_option = ' -fslgrad ' + path.from_user( app.ARGS.fslgrad[0]) + ' ' + path.from_user(app.ARGS.fslgrad[1]) if app.ARGS.percentile: intensities = [float(value) for value in run.command('dwiextract ' + path.from_user(app.ARGS.input_dwi) + grad_option + ' -bzero - | ' + \ 'mrmath - mean - -axis 3 | ' + \ 'mrdump - -mask ' + path.from_user(app.ARGS.input_mask)).stdout.splitlines()] reference_value = sorted(intensities)[int( round(0.01 * app.ARGS.percentile * len(intensities)))] else: reference_value = float(run.command('dwiextract ' + path.from_user(app.ARGS.input_dwi) + grad_option + ' -bzero - | ' + \ 'mrmath - mean - -axis 3 | ' + \ 'mrstats - -mask ' + path.from_user(app.ARGS.input_mask) + ' -output median -allvolumes').stdout) multiplier = app.ARGS.intensity / reference_value run.command('mrcalc ' + path.from_user(app.ARGS.input_dwi) + ' ' + str(multiplier) + ' -mult - | ' + \ 'mrconvert - ' + path.from_user(app.ARGS.output_dwi) + grad_option, \ mrconvert_keyval=path.from_user(app.ARGS.input_dwi), \ force=app.FORCE_OVERWRITE)
def get_inputs(): #pylint: disable=unused-variable from mrtrix3 import app, path, run run.command('mrconvert ' + path.from_user(app.ARGS.in_5tt) + ' ' + path.to_scratch('5tt.mif')) if app.ARGS.dirs: run.command('mrconvert ' + path.from_user(app.ARGS.dirs) + ' ' + path.to_scratch('dirs.mif') + ' -strides 0,0,0,1')
def getInputs(): #pylint: disable=unused-variable from mrtrix3 import app, path, run run.command('mrconvert ' + path.fromUser(app.args.in_5tt, True) + ' ' + path.toTemp('5tt.mif', True)) if app.args.dirs: run.command('mrconvert ' + path.fromUser(app.args.dirs, True) + ' ' + path.toTemp('dirs.mif', True) + ' -strides 0,0,0,1')
def execute(): #pylint: disable=unused-variable import os, shutil from mrtrix3 import app, image, path, run shells = [ int(round(float(x))) for x in image.mrinfo('dwi.mif', 'shell_bvalues').split() ] # Get lmax information (if provided) lmax = [ ] if app.args.lmax: lmax = [ int(x.strip()) for x in app.args.lmax.split(',') ] if not len(lmax) == len(shells): app.error('Number of manually-defined lmax\'s (' + str(len(lmax)) + ') does not match number of b-value shells (' + str(len(shells)) + ')') for l in lmax: if l%2: app.error('Values for lmax must be even') if l<0: app.error('Values for lmax must be non-negative') # Do we have directions, or do we need to calculate them? if not os.path.exists('dirs.mif'): run.command('dwi2tensor dwi.mif - -mask in_voxels.mif | tensor2metric - -vector dirs.mif') # Get response function bvalues_option = ' -shells ' + ','.join(map(str,shells)) lmax_option = '' if lmax: lmax_option = ' -lmax ' + ','.join(map(str,lmax)) run.command('amp2response dwi.mif in_voxels.mif dirs.mif response.txt' + bvalues_option + lmax_option) run.function(shutil.copyfile, 'response.txt', path.fromUser(app.args.output, False)) run.function(shutil.copyfile, 'in_voxels.mif', 'voxels.mif')
def execute(): #pylint: disable=unused-variable grad_option = '' if app.ARGS.grad: grad_option = ' -grad ' + path.from_user(app.ARGS.grad) elif app.ARGS.fslgrad: grad_option = ' -fslgrad ' + path.from_user(app.ARGS.fslgrad[0]) + ' ' + path.from_user(app.ARGS.fslgrad[1]) if app.ARGS.percentile: if app.ARGS.percentile < 0.0 or app.ARGS.percentile > 100.0: raise MRtrixError('-percentile value must be between 0 and 100') intensities = [float(value) for value in run.command('dwiextract ' + path.from_user(app.ARGS.input_dwi) + grad_option + ' -bzero - | ' + \ 'mrmath - mean - -axis 3 | ' + \ 'mrdump - -mask ' + path.from_user(app.ARGS.input_mask)).stdout.splitlines()] intensities = sorted(intensities) float_index = 0.01 * app.ARGS.percentile * len(intensities) lower_index = int(math.floor(float_index)) if app.ARGS.percentile == 100.0: reference_value = intensities[-1] else: interp_mu = float_index - float(lower_index) reference_value = (1.0-interp_mu)*intensities[lower_index] + interp_mu*intensities[lower_index+1] else: reference_value = float(run.command('dwiextract ' + path.from_user(app.ARGS.input_dwi) + grad_option + ' -bzero - | ' + \ 'mrmath - mean - -axis 3 | ' + \ 'mrstats - -mask ' + path.from_user(app.ARGS.input_mask) + ' -output median').stdout) multiplier = app.ARGS.intensity / reference_value run.command('mrcalc ' + path.from_user(app.ARGS.input_dwi) + ' ' + str(multiplier) + ' -mult - | ' + \ 'mrconvert - ' + path.from_user(app.ARGS.output_dwi) + grad_option, \ mrconvert_keyval=path.from_user(app.ARGS.input_dwi, False), \ force=app.FORCE_OVERWRITE)
def getInputs(): import os from mrtrix3 import app, path, run run.command('mrconvert ' + path.fromUser(app.args.in_5tt, True) + ' ' + path.toTemp('5tt.mif', True)) if app.args.dirs: run.command('mrconvert ' + path.fromUser(app.args.dirs, True) + ' ' + path.toTemp('dirs.mif', True) + ' -stride 0,0,0,1')
def getInputs(): import os, shutil from mrtrix3 import app, path, run run.command('mrconvert ' + path.fromUser(app.args.input, True) + ' ' + path.toTemp('input.mif', True)) if app.args.lut: run.function(shutil.copyfile, path.fromUser(app.args.lut, False), path.toTemp('LUT.txt', False))
def get_inputs(): #pylint: disable=unused-variable mask_path = path.to_scratch('mask.mif', False) if os.path.exists(mask_path): app.warn('-mask option is ignored by algorithm \'manual\'') os.remove(mask_path) run.command('mrconvert ' + path.from_user(app.ARGS.in_voxels) + ' ' + path.to_scratch('in_voxels.mif')) if app.ARGS.dirs: run.command('mrconvert ' + path.from_user(app.ARGS.dirs) + ' ' + path.to_scratch('dirs.mif') + ' -strides 0,0,0,1')
def getInputs(): import os from mrtrix3 import app, image, path, run if app.args.mask: run.command('mrconvert ' + path.fromUser(app.args.mask, True) + ' ' + path.toTemp('mask.mif', True) + ' -datatype bit -stride -1,+2,+3') if app.args.t2: if not image.match(app.args.input, app.args.t2): app.error('Provided T2 image does not match input T1 image') run.command('mrconvert ' + path.fromUser(app.args.t2, True) + ' ' + path.toTemp('T2.nii', True) + ' -stride -1,+2,+3')
def getInputs(): #pylint: disable=unused-variable import os from mrtrix3 import app, path, run mask_path = path.toTemp('mask.mif', False) if os.path.exists(mask_path): app.warn('-mask option is ignored by algorithm \'manual\'') os.remove(mask_path) run.command('mrconvert ' + path.fromUser(app.args.in_voxels, True) + ' ' + path.toTemp('in_voxels.mif', True)) if app.args.dirs: run.command('mrconvert ' + path.fromUser(app.args.dirs, True) + ' ' + path.toTemp('dirs.mif', True) + ' -strides 0,0,0,1')
def getInputs(): import os from mrtrix3 import app, path, run mask_path = path.toTemp('mask.mif', False) if os.path.exists(mask_path): app.warn('-mask option is ignored by algorithm \'manual\'') os.remove(mask_path) run.command('mrconvert ' + path.fromUser(app.args.in_voxels, True) + ' ' + path.toTemp('in_voxels.mif', True)) if app.args.dirs: run.command('mrconvert ' + path.fromUser(app.args.dirs, True) + ' ' + path.toTemp('dirs.mif', True) + ' -stride 0,0,0,1')
def __init__(self, message, value): from mrtrix3 import app, run #pylint: disable=import-outside-toplevel if isinstance(value, int): self.progress = app.ProgressBar(message, value) self.target_count = value self.counter = 0 self.valid = True elif isinstance(value, list): assert all(isinstance(entry, STRING_TYPES) for entry in value) self.progress = app.ProgressBar(message, len(value)) for entry in value: run.command(entry) self.progress.increment() self.progress.done() self.valid = False else: raise TypeError( 'Construction of RunList class expects either an ' 'integer (number of commands/functions to run), or a ' 'list of command strings to execute')
def execute(): #pylint: disable=unused-variable shells = [ int(round(float(x))) for x in image.mrinfo('dwi.mif', 'shell_bvalues').split() ] # Get lmax information (if provided) lmax = [ ] if app.ARGS.lmax: lmax = [ int(x.strip()) for x in app.ARGS.lmax.split(',') ] if not len(lmax) == len(shells): raise MRtrixError('Number of manually-defined lmax\'s (' + str(len(lmax)) + ') does not match number of b-value shells (' + str(len(shells)) + ')') for shell_l in lmax: if shell_l % 2: raise MRtrixError('Values for lmax must be even') if shell_l < 0: raise MRtrixError('Values for lmax must be non-negative') # Do we have directions, or do we need to calculate them? if not os.path.exists('dirs.mif'): run.command('dwi2tensor dwi.mif - -mask in_voxels.mif | tensor2metric - -vector dirs.mif') # Get response function bvalues_option = ' -shells ' + ','.join(map(str,shells)) lmax_option = '' if lmax: lmax_option = ' -lmax ' + ','.join(map(str,lmax)) run.command('amp2response dwi.mif in_voxels.mif dirs.mif response.txt' + bvalues_option + lmax_option) run.function(shutil.copyfile, 'response.txt', path.from_user(app.ARGS.output, False)) if app.ARGS.voxels: run.command('mrconvert in_voxels.mif ' + path.from_user(app.ARGS.voxels), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE)
def execute(): import os, shutil from mrtrix3 import app, image, path, run shells = [ int(round(float(x))) for x in image.headerField('dwi.mif', 'shells').split() ] # Get lmax information (if provided) lmax = [] if app.args.lmax: lmax = [int(x.strip()) for x in app.args.lmax.split(',')] if not len(lmax) == len(shells): app.error('Number of manually-defined lmax\'s (' + str(len(lmax)) + ') does not match number of b-value shells (' + str(len(shells)) + ')') for l in lmax: if l % 2: app.error('Values for lmax must be even') if l < 0: app.error('Values for lmax must be non-negative') # Do we have directions, or do we need to calculate them? if not os.path.exists('dirs.mif'): run.command( 'dwi2tensor dwi.mif - -mask in_voxels.mif | tensor2metric - -vector dirs.mif' ) # Get response function bvalues_option = ' -shell ' + ','.join(map(str, shells)) lmax_option = '' if lmax: lmax_option = ' -lmax ' + ','.join(map(str, lmax)) run.command('amp2response dwi.mif in_voxels.mif dirs.mif response.txt' + bvalues_option + lmax_option) run.function(shutil.copyfile, 'response.txt', path.fromUser(app.args.output, False)) run.function(shutil.copyfile, 'in_voxels.mif', 'voxels.mif')
def get_inputs(): #pylint: disable=unused-variable image.check_3d_nonunity(path.from_user(app.ARGS.input, False)) run.command('mrconvert ' + path.from_user(app.ARGS.input) + ' ' + path.to_scratch('input.mif')) if app.ARGS.mask: run.command('mrconvert ' + path.from_user(app.ARGS.mask) + ' ' + path.to_scratch('mask.mif') + ' -datatype bit -strides -1,+2,+3') if app.ARGS.t2: if not image.match(path.from_user(app.ARGS.input, False), path.from_user(app.ARGS.t2, False)): raise MRtrixError('Provided T2 image does not match input T1 image') run.command('mrconvert ' + path.from_user(app.ARGS.t2) + ' ' + path.to_scratch('T2.nii') + ' -strides -1,+2,+3')
def getInputs(): #pylint: disable=unused-variable from mrtrix3 import app, image, path, run image.check3DNonunity(path.fromUser(app.args.input, False)) run.command('mrconvert ' + path.fromUser(app.args.input, True) + ' ' + path.toTemp('input.mif', True)) if app.args.mask: run.command('mrconvert ' + path.fromUser(app.args.mask, True) + ' ' + path.toTemp('mask.mif', True) + ' -datatype bit -strides -1,+2,+3') if app.args.t2: if not image.match(app.args.input, app.args.t2): app.error('Provided T2 image does not match input T1 image') run.command('mrconvert ' + path.fromUser(app.args.t2, True) + ' ' + path.toTemp('T2.nii', True) + ' -strides -1,+2,+3')
def execute(): import math, os, shutil from mrtrix3 import app, image, path, run # Get b-values and number of volumes per b-value. bvalues = [ int(round(float(x))) for x in image.headerField('dwi.mif', 'shells').split() ] bvolumes = [ int(x) for x in image.headerField('dwi.mif', 'shellcounts').split() ] app.console(str(len(bvalues)) + ' unique b-value(s) detected: ' + ','.join(map(str,bvalues)) + ' with ' + ','.join(map(str,bvolumes)) + ' volumes.') if len(bvalues) < 2: app.error('Need at least 2 unique b-values (including b=0).') # Get lmax information (if provided). sfwm_lmax = [ ] if app.args.lmax: sfwm_lmax = [ int(x.strip()) for x in app.args.lmax.split(',') ] if not len(sfwm_lmax) == len(bvalues): app.error('Number of lmax\'s (' + str(len(sfwm_lmax)) + ', as supplied to the -lmax option: ' + ','.join(map(str,sfwm_lmax)) + ') does not match number of unique b-values.') for l in sfwm_lmax: if l%2: app.error('Values supplied to the -lmax option must be even.') if l<0: app.error('Values supplied to the -lmax option must be non-negative.') # Erode (brain) mask. if app.args.erode > 0: run.command('maskfilter mask.mif erode eroded_mask.mif -npass ' + str(app.args.erode)) else: run.command('mrconvert mask.mif eroded_mask.mif -datatype bit') # Get volumes, compute mean signal and SDM per b-value; compute overall SDM; get rid of erroneous values. totvolumes = 0 fullsdmcmd = 'mrcalc' errcmd = 'mrcalc' zeropath = 'mean_b' + str(bvalues[0]) + '.mif' for i, b in enumerate(bvalues): meanpath = 'mean_b' + str(b) + '.mif' run.command('dwiextract dwi.mif -shell ' + str(b) + ' - | mrmath - mean ' + meanpath + ' -axis 3') errpath = 'err_b' + str(b) + '.mif' run.command('mrcalc ' + meanpath + ' -finite ' + meanpath + ' 0 -if 0 -le ' + errpath + ' -datatype bit') errcmd += ' ' + errpath if i>0: errcmd += ' -add' sdmpath = 'sdm_b' + str(b) + '.mif' run.command('mrcalc ' + zeropath + ' ' + meanpath + ' -divide -log ' + sdmpath) totvolumes += bvolumes[i] fullsdmcmd += ' ' + sdmpath + ' ' + str(bvolumes[i]) + ' -mult' if i>1: fullsdmcmd += ' -add' fullsdmcmd += ' ' + str(totvolumes) + ' -divide full_sdm.mif' run.command(fullsdmcmd) run.command('mrcalc full_sdm.mif -finite full_sdm.mif 0 -if 0 -le err_sdm.mif -datatype bit') errcmd += ' err_sdm.mif -add 0 eroded_mask.mif -if safe_mask.mif -datatype bit' run.command(errcmd) run.command('mrcalc safe_mask.mif full_sdm.mif 0 -if 10 -min safe_sdm.mif') # Compute FA and principal eigenvectors; crude WM versus GM-CSF separation based on FA. run.command('dwi2tensor dwi.mif - -mask safe_mask.mif | tensor2metric - -fa safe_fa.mif -vector safe_vecs.mif -modulate none -mask safe_mask.mif') run.command('mrcalc safe_mask.mif safe_fa.mif 0 -if ' + str(app.args.fa) + ' -gt crude_wm.mif -datatype bit') run.command('mrcalc crude_wm.mif 0 safe_mask.mif -if _crudenonwm.mif -datatype bit') # Crude GM versus CSF separation based on SDM. crudenonwmmedian = image.statistic('safe_sdm.mif', 'median', '_crudenonwm.mif') run.command('mrcalc _crudenonwm.mif safe_sdm.mif ' + str(crudenonwmmedian) + ' -subtract 0 -if - | mrthreshold - - -mask _crudenonwm.mif | mrcalc _crudenonwm.mif - 0 -if crude_csf.mif -datatype bit') run.command('mrcalc crude_csf.mif 0 _crudenonwm.mif -if crude_gm.mif -datatype bit') # Refine WM: remove high SDM outliers. crudewmmedian = image.statistic('safe_sdm.mif', 'median', 'crude_wm.mif') run.command('mrcalc crude_wm.mif safe_sdm.mif 0 -if ' + str(crudewmmedian) + ' -gt _crudewmhigh.mif -datatype bit') run.command('mrcalc _crudewmhigh.mif 0 crude_wm.mif -if _crudewmlow.mif -datatype bit') crudewmQ1 = float(image.statistic('safe_sdm.mif', 'median', '_crudewmlow.mif')) crudewmQ3 = float(image.statistic('safe_sdm.mif', 'median', '_crudewmhigh.mif')) crudewmoutlthresh = crudewmQ3 + (crudewmQ3 - crudewmQ1) run.command('mrcalc crude_wm.mif safe_sdm.mif 0 -if ' + str(crudewmoutlthresh) + ' -gt _crudewmoutliers.mif -datatype bit') run.command('mrcalc _crudewmoutliers.mif 0 crude_wm.mif -if refined_wm.mif -datatype bit') # Refine GM: separate safer GM from partial volumed voxels. crudegmmedian = image.statistic('safe_sdm.mif', 'median', 'crude_gm.mif') run.command('mrcalc crude_gm.mif safe_sdm.mif 0 -if ' + str(crudegmmedian) + ' -gt _crudegmhigh.mif -datatype bit') run.command('mrcalc _crudegmhigh.mif 0 crude_gm.mif -if _crudegmlow.mif -datatype bit') run.command('mrcalc _crudegmhigh.mif safe_sdm.mif ' + str(crudegmmedian) + ' -subtract 0 -if - | mrthreshold - - -mask _crudegmhigh.mif -invert | mrcalc _crudegmhigh.mif - 0 -if _crudegmhighselect.mif -datatype bit') run.command('mrcalc _crudegmlow.mif safe_sdm.mif ' + str(crudegmmedian) + ' -subtract -neg 0 -if - | mrthreshold - - -mask _crudegmlow.mif -invert | mrcalc _crudegmlow.mif - 0 -if _crudegmlowselect.mif -datatype bit') run.command('mrcalc _crudegmhighselect.mif 1 _crudegmlowselect.mif -if refined_gm.mif -datatype bit') # Refine CSF: recover lost CSF from crude WM SDM outliers, separate safer CSF from partial volumed voxels. crudecsfmin = image.statistic('safe_sdm.mif', 'min', 'crude_csf.mif') run.command('mrcalc _crudewmoutliers.mif safe_sdm.mif 0 -if ' + str(crudecsfmin) + ' -gt 1 crude_csf.mif -if _crudecsfextra.mif -datatype bit') run.command('mrcalc _crudecsfextra.mif safe_sdm.mif ' + str(crudecsfmin) + ' -subtract 0 -if - | mrthreshold - - -mask _crudecsfextra.mif | mrcalc _crudecsfextra.mif - 0 -if refined_csf.mif -datatype bit') # Get final voxels for single-fibre WM response function estimation from WM using 'tournier' algorithm. refwmcount = float(image.statistic('refined_wm.mif', 'count', 'refined_wm.mif')) voxsfwmcount = int(round(refwmcount * app.args.sfwm / 100.0)) app.console('Running \'tournier\' algorithm to select ' + str(voxsfwmcount) + ' single-fibre WM voxels.') cleanopt = '' if not app._cleanup: cleanopt = ' -nocleanup' run.command('dwi2response tournier dwi.mif _respsfwmss.txt -sf_voxels ' + str(voxsfwmcount) + ' -iter_voxels ' + str(voxsfwmcount * 10) + ' -mask refined_wm.mif -voxels voxels_sfwm.mif -tempdir ' + app._tempDir + cleanopt) # Get final voxels for GM response function estimation from GM. refgmmedian = image.statistic('safe_sdm.mif', 'median', 'refined_gm.mif') run.command('mrcalc refined_gm.mif safe_sdm.mif 0 -if ' + str(refgmmedian) + ' -gt _refinedgmhigh.mif -datatype bit') run.command('mrcalc _refinedgmhigh.mif 0 refined_gm.mif -if _refinedgmlow.mif -datatype bit') refgmhighcount = float(image.statistic('_refinedgmhigh.mif', 'count', '_refinedgmhigh.mif')) refgmlowcount = float(image.statistic('_refinedgmlow.mif', 'count', '_refinedgmlow.mif')) voxgmhighcount = int(round(refgmhighcount * app.args.gm / 100.0)) voxgmlowcount = int(round(refgmlowcount * app.args.gm / 100.0)) run.command('mrcalc _refinedgmhigh.mif safe_sdm.mif 0 -if - | mrthreshold - - -bottom ' + str(voxgmhighcount) + ' -ignorezero | mrcalc _refinedgmhigh.mif - 0 -if _refinedgmhighselect.mif -datatype bit') run.command('mrcalc _refinedgmlow.mif safe_sdm.mif 0 -if - | mrthreshold - - -top ' + str(voxgmlowcount) + ' -ignorezero | mrcalc _refinedgmlow.mif - 0 -if _refinedgmlowselect.mif -datatype bit') run.command('mrcalc _refinedgmhighselect.mif 1 _refinedgmlowselect.mif -if voxels_gm.mif -datatype bit') # Get final voxels for CSF response function estimation from CSF. refcsfcount = float(image.statistic('refined_csf.mif', 'count', 'refined_csf.mif')) voxcsfcount = int(round(refcsfcount * app.args.csf / 100.0)) run.command('mrcalc refined_csf.mif safe_sdm.mif 0 -if - | mrthreshold - - -top ' + str(voxcsfcount) + ' -ignorezero | mrcalc refined_csf.mif - 0 -if voxels_csf.mif -datatype bit') # Show summary of voxels counts. textarrow = ' --> ' app.console('Summary of voxel counts:') app.console('Mask: ' + str(int(image.statistic('mask.mif', 'count', 'mask.mif'))) + textarrow + str(int(image.statistic('eroded_mask.mif', 'count', 'eroded_mask.mif'))) + textarrow + str(int(image.statistic('safe_mask.mif', 'count', 'safe_mask.mif')))) app.console('WM: ' + str(int(image.statistic('crude_wm.mif', 'count', 'crude_wm.mif'))) + textarrow + str(int(image.statistic('refined_wm.mif', 'count', 'refined_wm.mif'))) + textarrow + str(int(image.statistic('voxels_sfwm.mif', 'count', 'voxels_sfwm.mif'))) + ' (SF)') app.console('GM: ' + str(int(image.statistic('crude_gm.mif', 'count', 'crude_gm.mif'))) + textarrow + str(int(image.statistic('refined_gm.mif', 'count', 'refined_gm.mif'))) + textarrow + str(int(image.statistic('voxels_gm.mif', 'count', 'voxels_gm.mif')))) app.console('CSF: ' + str(int(image.statistic('crude_csf.mif', 'count', 'crude_csf.mif'))) + textarrow + str(int(image.statistic('refined_csf.mif', 'count', 'refined_csf.mif'))) + textarrow + str(int(image.statistic('voxels_csf.mif', 'count', 'voxels_csf.mif')))) # Generate single-fibre WM, GM and CSF responses bvalues_option = ' -shell ' + ','.join(map(str,bvalues)) sfwm_lmax_option = '' if sfwm_lmax: sfwm_lmax_option = ' -lmax ' + ','.join(map(str,sfwm_lmax)) run.command('amp2response dwi.mif voxels_sfwm.mif safe_vecs.mif response_sfwm.txt' + bvalues_option + sfwm_lmax_option) run.command('amp2response dwi.mif voxels_gm.mif safe_vecs.mif response_gm.txt' + bvalues_option + ' -isotropic') run.command('amp2response dwi.mif voxels_csf.mif safe_vecs.mif response_csf.txt' + bvalues_option + ' -isotropic') run.function(shutil.copyfile, 'response_sfwm.txt', path.fromUser(app.args.out_sfwm, False)) run.function(shutil.copyfile, 'response_gm.txt', path.fromUser(app.args.out_gm, False)) run.function(shutil.copyfile, 'response_csf.txt', path.fromUser(app.args.out_csf, False)) # Generate 4D binary images with voxel selections at major stages in algorithm (RGB as in MSMT-CSD paper). run.command('mrcat crude_csf.mif crude_gm.mif crude_wm.mif crude.mif -axis 3') run.command('mrcat refined_csf.mif refined_gm.mif refined_wm.mif refined.mif -axis 3') run.command('mrcat voxels_csf.mif voxels_gm.mif voxels_sfwm.mif voxels.mif -axis 3')
def execute(): #pylint: disable=unused-variable import math, os, shutil from mrtrix3 import app, image, matrix, MRtrixError, path, run lmax_option = '' if app.ARGS.lmax: lmax_option = ' -lmax ' + app.ARGS.lmax convergence_change = 0.01 * app.ARGS.convergence progress = app.ProgressBar('Optimising') iteration = 0 while iteration < app.ARGS.max_iters: prefix = 'iter' + str(iteration) + '_' # How to initialise response function? # old dwi2response command used mean & standard deviation of DWI data; however # this may force the output FODs to lmax=2 at the first iteration # Chantal used a tensor with low FA, but it'd be preferable to get the scaling right # Other option is to do as before, but get the ratio between l=0 and l=2, and # generate l=4,6,... using that amplitude ratio if iteration == 0: rf_in_path = 'init_RF.txt' mask_in_path = 'mask.mif' # Grab the mean and standard deviation across all volumes in a single mrstats call # Also scale them to reflect the fact that we're moving to the SH basis mean = image.statistic('dwi.mif', 'mean', '-mask mask.mif -allvolumes') * math.sqrt( 4.0 * math.pi) std = image.statistic('dwi.mif', 'std', '-mask mask.mif -allvolumes') * math.sqrt( 4.0 * math.pi) # Now produce the initial response function # Let's only do it to lmax 4 init_rf = [ str(mean), str(-0.5 * std), str(0.25 * std * std / mean) ] with open('init_RF.txt', 'w') as init_rf_file: init_rf_file.write(' '.join(init_rf)) else: rf_in_path = 'iter' + str(iteration - 1) + '_RF.txt' mask_in_path = 'iter' + str(iteration - 1) + '_SF.mif' # Run CSD run.command('dwi2fod csd dwi.mif ' + rf_in_path + ' ' + prefix + 'FOD.mif -mask ' + mask_in_path) # Get amplitudes of two largest peaks, and directions of largest run.command('fod2fixel ' + prefix + 'FOD.mif ' + prefix + 'fixel -peak peaks.mif -mask ' + mask_in_path + ' -fmls_no_thresholds') app.cleanup(prefix + 'FOD.mif') run.command('fixel2voxel ' + prefix + 'fixel/peaks.mif split_data ' + prefix + 'amps.mif') run.command('mrconvert ' + prefix + 'amps.mif ' + prefix + 'first_peaks.mif -coord 3 0 -axes 0,1,2') run.command('mrconvert ' + prefix + 'amps.mif ' + prefix + 'second_peaks.mif -coord 3 1 -axes 0,1,2') app.cleanup(prefix + 'amps.mif') run.command('fixel2voxel ' + prefix + 'fixel/directions.mif split_dir ' + prefix + 'all_dirs.mif') app.cleanup(prefix + 'fixel') run.command('mrconvert ' + prefix + 'all_dirs.mif ' + prefix + 'first_dir.mif -coord 3 0:2') app.cleanup(prefix + 'all_dirs.mif') # Revise single-fibre voxel selection based on ratio of tallest to second-tallest peak run.command('mrcalc ' + prefix + 'second_peaks.mif ' + prefix + 'first_peaks.mif -div ' + prefix + 'peak_ratio.mif') app.cleanup(prefix + 'first_peaks.mif') app.cleanup(prefix + 'second_peaks.mif') run.command('mrcalc ' + prefix + 'peak_ratio.mif ' + str(app.ARGS.peak_ratio) + ' -lt ' + mask_in_path + ' -mult ' + prefix + 'SF.mif -datatype bit') app.cleanup(prefix + 'peak_ratio.mif') # Make sure image isn't empty sf_voxel_count = image.statistic(prefix + 'SF.mif', 'count', '-mask ' + prefix + 'SF.mif') if not sf_voxel_count: raise MRtrixError( 'Aborting: All voxels have been excluded from single-fibre selection' ) # Generate a new response function run.command('amp2response dwi.mif ' + prefix + 'SF.mif ' + prefix + 'first_dir.mif ' + prefix + 'RF.txt' + lmax_option) app.cleanup(prefix + 'first_dir.mif') new_rf = matrix.load_vector(prefix + 'RF.txt') progress.increment('Optimising (' + str(iteration + 1) + ' iterations, ' + str(sf_voxel_count) + ' voxels, RF: [ ' + ', '.join('{:.3f}'.format(n) for n in new_rf) + '] )') # Detect convergence # Look for a change > some percentage - don't bother looking at the masks if iteration > 0: old_rf = matrix.load_vector(rf_in_path) reiterate = False for old_value, new_value in zip(old_rf, new_rf): mean = 0.5 * (old_value + new_value) diff = math.fabs(0.5 * (old_value - new_value)) ratio = diff / mean if ratio > convergence_change: reiterate = True if not reiterate: run.function(shutil.copyfile, prefix + 'RF.txt', 'response.txt') run.function(shutil.copyfile, prefix + 'SF.mif', 'voxels.mif') break app.cleanup(rf_in_path) app.cleanup(mask_in_path) iteration += 1 progress.done() # If we've terminated due to hitting the iteration limiter, we still need to copy the output file(s) to the correct location if os.path.exists('response.txt'): app.console('Exited at iteration ' + str(iteration + 1) + ' with ' + str(sf_voxel_count) + ' SF voxels due to unchanged RF coefficients') else: app.console('Exited after maximum ' + str(app.ARGS.max_iters) + ' iterations with ' + str(sf_voxel_count) + ' SF voxels') run.function(shutil.copyfile, 'iter' + str(app.ARGS.max_iters - 1) + '_RF.txt', 'response.txt') run.function(shutil.copyfile, 'iter' + str(app.ARGS.max_iters - 1) + '_SF.mif', 'voxels.mif') run.function(shutil.copyfile, 'response.txt', path.from_user(app.ARGS.output, False)) if app.ARGS.voxels: run.command('mrconvert voxels.mif ' + path.from_user(app.ARGS.voxels), mrconvert_keyval=path.from_user(app.ARGS.input), force=app.FORCE_OVERWRITE)
def execute(): #pylint: disable=unused-variable import os.path #pylint: disable=unused-variable from mrtrix3 import app, path, run lut_input_path = 'LUT.txt' if not os.path.exists('LUT.txt'): freesurfer_home = os.environ.get('FREESURFER_HOME', '') if not freesurfer_home: app.error('Environment variable FREESURFER_HOME is not set; please run appropriate FreeSurfer configuration script, set this variable manually, or provide script with path to file FreeSurferColorLUT.txt using -lut option') lut_input_path = os.path.join(freesurfer_home, 'FreeSurferColorLUT.txt') if not os.path.isfile(lut_input_path): app.error('Could not find FreeSurfer lookup table file (expected location: ' + lut_input_path + '), and none provided using -lut') if app.args.sgm_amyg_hipp: lut_output_file_name = 'FreeSurfer2ACT_sgm_amyg_hipp.txt' else: lut_output_file_name = 'FreeSurfer2ACT.txt' lut_output_path = os.path.join(path.sharedDataPath(), path.scriptSubDirName(), lut_output_file_name) if not os.path.isfile(lut_output_path): app.error('Could not find lookup table file for converting FreeSurfer parcellation output to tissues (expected location: ' + lut_output_path + ')') # Initial conversion from FreeSurfer parcellation to five principal tissue types run.command('labelconvert input.mif ' + lut_input_path + ' ' + lut_output_path + ' indices.mif') # Use mrcrop to reduce file size if app.args.nocrop: image = 'indices.mif' else: image = 'indices_cropped.mif' run.command('mrthreshold indices.mif - -abs 0.5 | mrcrop indices.mif ' + image + ' -mask -') # Convert into the 5TT format for ACT run.command('mrcalc ' + image + ' 1 -eq cgm.mif') run.command('mrcalc ' + image + ' 2 -eq sgm.mif') run.command('mrcalc ' + image + ' 3 -eq wm.mif') run.command('mrcalc ' + image + ' 4 -eq csf.mif') run.command('mrcalc ' + image + ' 5 -eq path.mif') run.command('mrcat cgm.mif sgm.mif wm.mif csf.mif path.mif - -axis 3 | mrconvert - result.mif -datatype float32')
def execute(): #pylint: disable=unused-variable # Generate the images related to each tissue run.command('mrconvert input.mif -coord 3 1 CSF.mif') run.command('mrconvert input.mif -coord 3 2 cGM.mif') run.command('mrconvert input.mif -coord 3 3 cWM.mif') run.command('mrconvert input.mif -coord 3 4 sGM.mif') # Combine WM and subcortical WM into a unique WM image run.command( 'mrconvert input.mif - -coord 3 3,5 | mrmath - sum WM.mif -axis 3') # Create an empty lesion image run.command('mrcalc WM.mif 0 -mul lsn.mif') # Convert into the 5tt format run.command('mrcat cGM.mif sGM.mif WM.mif CSF.mif lsn.mif 5tt.mif -axis 3') if app.ARGS.nocrop: run.function(os.rename, '5tt.mif', 'result.mif') else: run.command( 'mrmath 5tt.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrgrid 5tt.mif crop result.mif -mask -' ) run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE)
def execute(): #pylint: disable=unused-variable import os, shutil from mrtrix3 import app, file, image, path, run #pylint: disable=redefined-builtin lmax_option = '' if app.args.lmax: lmax_option = ' -lmax ' + app.args.lmax if app.args.max_iters < 2: app.error('Number of iterations must be at least 2') for iteration in range(0, app.args.max_iters): prefix = 'iter' + str(iteration) + '_' if iteration == 0: RF_in_path = 'init_RF.txt' mask_in_path = 'mask.mif' init_RF = '1 -1 1' with open(RF_in_path, 'w') as f: f.write(init_RF) iter_lmax_option = ' -lmax 4' else: RF_in_path = 'iter' + str(iteration - 1) + '_RF.txt' mask_in_path = 'iter' + str(iteration - 1) + '_SF_dilated.mif' iter_lmax_option = lmax_option # Run CSD run.command('dwi2fod csd dwi.mif ' + RF_in_path + ' ' + prefix + 'FOD.mif -mask ' + mask_in_path + iter_lmax_option) # Get amplitudes of two largest peaks, and direction of largest run.command('fod2fixel ' + prefix + 'FOD.mif ' + prefix + 'fixel -peak peaks.mif -mask ' + mask_in_path + ' -fmls_no_thresholds') file.delTemporary(prefix + 'FOD.mif') if iteration: file.delTemporary(mask_in_path) run.command('fixel2voxel ' + prefix + 'fixel/peaks.mif split_data ' + prefix + 'amps.mif -number 2') run.command('mrconvert ' + prefix + 'amps.mif ' + prefix + 'first_peaks.mif -coord 3 0 -axes 0,1,2') run.command('mrconvert ' + prefix + 'amps.mif ' + prefix + 'second_peaks.mif -coord 3 1 -axes 0,1,2') file.delTemporary(prefix + 'amps.mif') run.command('fixel2voxel ' + prefix + 'fixel/directions.mif split_dir ' + prefix + 'all_dirs.mif -number 1') file.delTemporary(prefix + 'fixel') run.command('mrconvert ' + prefix + 'all_dirs.mif ' + prefix + 'first_dir.mif -coord 3 0:2') file.delTemporary(prefix + 'all_dirs.mif') # Calculate the 'cost function' Donald derived for selecting single-fibre voxels # https://github.com/MRtrix3/mrtrix3/pull/426 # sqrt(|peak1|) * (1 - |peak2| / |peak1|)^2 run.command('mrcalc ' + prefix + 'first_peaks.mif -sqrt 1 ' + prefix + 'second_peaks.mif ' + prefix + 'first_peaks.mif -div -sub 2 -pow -mult ' + prefix + 'CF.mif') file.delTemporary(prefix + 'first_peaks.mif') file.delTemporary(prefix + 'second_peaks.mif') # Select the top-ranked voxels run.command('mrthreshold ' + prefix + 'CF.mif -top ' + str(app.args.sf_voxels) + ' ' + prefix + 'SF.mif') # Generate a new response function based on this selection run.command('amp2response dwi.mif ' + prefix + 'SF.mif ' + prefix + 'first_dir.mif ' + prefix + 'RF.txt' + iter_lmax_option) file.delTemporary(prefix + 'first_dir.mif') # Should we terminate? if iteration > 0: run.command('mrcalc ' + prefix + 'SF.mif iter' + str(iteration - 1) + '_SF.mif -sub ' + prefix + 'SF_diff.mif') file.delTemporary('iter' + str(iteration - 1) + '_SF.mif') max_diff = image.statistic(prefix + 'SF_diff.mif', 'max') file.delTemporary(prefix + 'SF_diff.mif') if int(max_diff) == 0: app.console( 'Convergence of SF voxel selection detected at iteration ' + str(iteration)) file.delTemporary(prefix + 'CF.mif') run.function(shutil.copyfile, prefix + 'RF.txt', 'response.txt') run.function(shutil.move, prefix + 'SF.mif', 'voxels.mif') break # Select a greater number of top single-fibre voxels, and dilate (within bounds of initial mask); # these are the voxels that will be re-tested in the next iteration run.command('mrthreshold ' + prefix + 'CF.mif -top ' + str(app.args.iter_voxels) + ' - | maskfilter - dilate - -npass ' + str(app.args.dilate) + ' | mrcalc mask.mif - -mult ' + prefix + 'SF_dilated.mif') file.delTemporary(prefix + 'CF.mif') # Commence the next iteration # If terminating due to running out of iterations, still need to put the results in the appropriate location if not os.path.exists('response.txt'): app.console('Exiting after maximum ' + str(app.args.max_iters) + ' iterations') run.function(shutil.copyfile, 'iter' + str(app.args.max_iters - 1) + '_RF.txt', 'response.txt') run.function(shutil.move, 'iter' + str(app.args.max_iters - 1) + '_SF.mif', 'voxels.mif') run.function(shutil.copyfile, 'response.txt', path.fromUser(app.args.output, False))
def execute(): #pylint: disable=unused-variable lut_input_path = 'LUT.txt' if not os.path.exists('LUT.txt'): freesurfer_home = os.environ.get('FREESURFER_HOME', '') if not freesurfer_home: raise MRtrixError( 'Environment variable FREESURFER_HOME is not set; please run appropriate FreeSurfer configuration script, set this variable manually, or provide script with path to file FreeSurferColorLUT.txt using -lut option' ) lut_input_path = os.path.join(freesurfer_home, 'FreeSurferColorLUT.txt') if not os.path.isfile(lut_input_path): raise MRtrixError( 'Could not find FreeSurfer lookup table file (expected location: ' + lut_input_path + '), and none provided using -lut') if app.ARGS.sgm_amyg_hipp: lut_output_file_name = 'FreeSurfer2ACT_sgm_amyg_hipp.txt' else: lut_output_file_name = 'FreeSurfer2ACT.txt' lut_output_path = os.path.join(path.shared_data_path(), path.script_subdir_name(), lut_output_file_name) if not os.path.isfile(lut_output_path): raise MRtrixError( 'Could not find lookup table file for converting FreeSurfer parcellation output to tissues (expected location: ' + lut_output_path + ')') # Initial conversion from FreeSurfer parcellation to five principal tissue types run.command('labelconvert input.mif ' + lut_input_path + ' ' + lut_output_path + ' indices.mif') # Crop to reduce file size if app.ARGS.nocrop: image = 'indices.mif' else: image = 'indices_cropped.mif' run.command( 'mrthreshold indices.mif - -abs 0.5 | mrgrid indices.mif crop ' + image + ' -mask -') # Convert into the 5TT format for ACT run.command('mrcalc ' + image + ' 1 -eq cgm.mif') run.command('mrcalc ' + image + ' 2 -eq sgm.mif') run.command('mrcalc ' + image + ' 3 -eq wm.mif') run.command('mrcalc ' + image + ' 4 -eq csf.mif') run.command('mrcalc ' + image + ' 5 -eq path.mif') run.command( 'mrcat cgm.mif sgm.mif wm.mif csf.mif path.mif - -axis 3 | mrconvert - result.mif -datatype float32' ) run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE)
def execute(): #pylint: disable=unused-variable class Input(object): def __init__(self, filename, prefix, mask_filename=''): self.filename = filename self.prefix = prefix self.mask_filename = mask_filename input_dir = path.from_user(app.ARGS.input_dir, False) if not os.path.exists(input_dir): raise MRtrixError('input directory not found') in_files = path.all_in_dir(input_dir, dir_path=False) if len(in_files) <= 1: raise MRtrixError( 'not enough images found in input directory: more than one image is needed to perform a group-wise intensity normalisation' ) app.console('performing global intensity normalisation on ' + str(len(in_files)) + ' input images') mask_dir = path.from_user(app.ARGS.mask_dir, False) if not os.path.exists(mask_dir): raise MRtrixError('mask directory not found') mask_files = path.all_in_dir(mask_dir, dir_path=False) if len(mask_files) != len(in_files): raise MRtrixError( 'the number of images in the mask directory does not equal the number of images in the input directory' ) mask_common_postfix = os.path.commonprefix([i[::-1] for i in mask_files])[::-1] mask_prefixes = [] for mask_file in mask_files: mask_prefixes.append(mask_file.split(mask_common_postfix)[0]) common_postfix = os.path.commonprefix([i[::-1] for i in in_files])[::-1] input_list = [] for i in in_files: subj_prefix = i.split(common_postfix)[0] if subj_prefix not in mask_prefixes: raise MRtrixError( 'no matching mask image was found for input image ' + i) image.check_3d_nonunity(os.path.join(input_dir, i)) index = mask_prefixes.index(subj_prefix) input_list.append(Input(i, subj_prefix, mask_files[index])) app.make_scratch_dir() app.goto_scratch_dir() path.make_dir('fa') progress = app.ProgressBar('Computing FA images', len(input_list)) for i in input_list: run.command('dwi2tensor ' + path.quote(os.path.join(input_dir, i.filename)) + ' -mask ' + path.quote(os.path.join(mask_dir, i.mask_filename)) + ' - | tensor2metric - -fa ' + os.path.join('fa', i.prefix + '.mif')) progress.increment() progress.done() app.console('Generating FA population template') run.command('population_template fa fa_template.mif' + ' -mask_dir ' + mask_dir + ' -type rigid_affine_nonlinear' + ' -rigid_scale 0.25,0.5,0.8,1.0' + ' -affine_scale 0.7,0.8,1.0,1.0' + ' -nl_scale 0.5,0.75,1.0,1.0,1.0' + ' -nl_niter 5,5,5,5,5' + ' -warp_dir warps' + ' -linear_no_pause' + ' -scratch population_template' + ('' if app.DO_CLEANUP else ' -nocleanup')) app.console('Generating WM mask in template space') run.command('mrthreshold fa_template.mif -abs ' + app.ARGS.fa_threshold + ' template_wm_mask.mif') progress = app.ProgressBar('Intensity normalising subject images', len(input_list)) path.make_dir(path.from_user(app.ARGS.output_dir, False)) path.make_dir('wm_mask_warped') for i in input_list: run.command( 'mrtransform template_wm_mask.mif -interp nearest -warp_full ' + os.path.join('warps', i.prefix + '.mif') + ' ' + os.path.join('wm_mask_warped', i.prefix + '.mif') + ' -from 2 -template ' + os.path.join('fa', i.prefix + '.mif')) run.command('dwinormalise individual ' + path.quote(os.path.join(input_dir, i.filename)) + ' ' + os.path.join('wm_mask_warped', i.prefix + '.mif') + ' temp.mif') run.command( 'mrconvert temp.mif ' + path.from_user(os.path.join(app.ARGS.output_dir, i.filename)), mrconvert_keyval=path.from_user( os.path.join(input_dir, i.filename), False), force=app.FORCE_OVERWRITE) os.remove('temp.mif') progress.increment() progress.done() app.console('Exporting template images to user locations') run.command('mrconvert template_wm_mask.mif ' + path.from_user(app.ARGS.wm_mask), mrconvert_keyval='NULL', force=app.FORCE_OVERWRITE) run.command('mrconvert fa_template.mif ' + path.from_user(app.ARGS.fa_template), mrconvert_keyval='NULL', force=app.FORCE_OVERWRITE)
def getInputs(): #pylint: disable=unused-variable from mrtrix3 import app, path, run checkGIFinput(path.fromUser(app.args.input, True)) run.command('mrconvert ' + path.fromUser(app.args.input, True) + ' ' + path.toTemp('input.mif', True))
def execute(): #pylint: disable=unused-variable from mrtrix3 import app, run # Generate the images related to each tissue run.command('mrconvert input.mif -coord 3 1 CSF.mif') run.command('mrconvert input.mif -coord 3 2 cGM.mif') run.command('mrconvert input.mif -coord 3 3 cWM.mif') run.command('mrconvert input.mif -coord 3 4 sGM.mif') # Combine WM and subcortical WM into a unique WM image run.command('mrconvert input.mif - -coord 3 3,5 | mrmath - sum WM.mif -axis 3') # Create an empty lesion image run.command('mrcalc WM.mif 0 -mul lsn.mif') # Convert into the 5tt format run.command('mrcat cGM.mif sGM.mif WM.mif CSF.mif lsn.mif 5tt.mif -axis 3') if app.args.nocrop: run.command('mrconvert 5tt.mif result.mif') else: run.command('mrmath 5tt.mif sum - -axis 3 | mrthreshold - - -abs 0.5 | mrcrop 5tt.mif result.mif -mask -')
if not app.args.fslbval: bvallist = [i + '.bval' for i in DWInlist] else: UserBvalpath = app.args.fslbval.rsplit(',') bvallist = [os.path.realpath(i) for i in UserBvalpath] if not app.args.fslbvec: bveclist = [i + '.bvec' for i in DWInlist] else: UserBvecpath = app.args.fslbvec.rsplit(',') bveclist = [os.path.realpath(i) for i in UserBvecpath] if len(DWInlist) == 1: if not isdicom: run.command('mrconvert -stride -1,2,3,4 -fslgrad ' + bveclist[0] + ' ' + bvallist[0] + ' ' + ''.join(DWInlist) + ''.join(DWIext) + ' ' + path.toTemp('dwi.mif', True)) else: run.command('mrconvert -stride -1,2,3,4 ' + ''.join(DWInlist) + ' ' + path.toTemp('dwi.mif', True)) else: for idx, i in enumerate(DWInlist): if not isdicom: run.command('mrconvert -stride -1,2,3,4 -fslgrad ' + bveclist[idx] + ' ' + bvallist[idx] + ' ' + i + DWIext[idx] + ' ' + path.toTemp('dwi' + str(idx) + '.mif', True)) else: run.command('mrconvert -stride -1,2,3,4 ' + i + ' ' + path.toTemp('dwi' + str(idx) + '.mif', True)) dwi_header = image.Header(path.toTemp('dwi' + str(idx) + '.mif', True))
def execute(): import math, os, shutil from mrtrix3 import app, file, image, path, run lmax_option = '' if app.args.lmax: lmax_option = ' -lmax ' + app.args.lmax convergence_change = 0.01 * app.args.convergence for iteration in range(0, app.args.max_iters): prefix = 'iter' + str(iteration) + '_' # How to initialise response function? # old dwi2response command used mean & standard deviation of DWI data; however # this may force the output FODs to lmax=2 at the first iteration # Chantal used a tensor with low FA, but it'd be preferable to get the scaling right # Other option is to do as before, but get the ratio between l=0 and l=2, and # generate l=4,6,... using that amplitude ratio if iteration == 0: RF_in_path = 'init_RF.txt' mask_in_path = 'mask.mif' # TODO This can be changed once #71 is implemented (mrstats statistics across volumes) volume_means = [float(x) for x in image.statistic('dwi.mif', 'mean', 'mask.mif').split()] mean = sum(volume_means) / float(len(volume_means)) volume_stds = [float(x) for x in image.statistic('dwi.mif', 'std', 'mask.mif').split()] std = sum(volume_stds) / float(len(volume_stds)) # Scale these to reflect the fact that we're moving to the SH basis mean *= math.sqrt(4.0 * math.pi) std *= math.sqrt(4.0 * math.pi) # Now produce the initial response function # Let's only do it to lmax 4 init_RF = [ str(mean), str(-0.5*std), str(0.25*std*std/mean) ] with open('init_RF.txt', 'w') as f: f.write(' '.join(init_RF)) else: RF_in_path = 'iter' + str(iteration-1) + '_RF.txt' mask_in_path = 'iter' + str(iteration-1) + '_SF.mif' # Run CSD run.command('dwi2fod csd dwi.mif ' + RF_in_path + ' ' + prefix + 'FOD.mif -mask ' + mask_in_path) # Get amplitudes of two largest peaks, and directions of largest run.command('fod2fixel ' + prefix + 'FOD.mif ' + prefix + 'fixel -peak peaks.mif -mask ' + mask_in_path + ' -fmls_no_thresholds') file.delTempFile(prefix + 'FOD.mif') run.command('fixel2voxel ' + prefix + 'fixel/peaks.mif split_data ' + prefix + 'amps.mif') run.command('mrconvert ' + prefix + 'amps.mif ' + prefix + 'first_peaks.mif -coord 3 0 -axes 0,1,2') run.command('mrconvert ' + prefix + 'amps.mif ' + prefix + 'second_peaks.mif -coord 3 1 -axes 0,1,2') file.delTempFile(prefix + 'amps.mif') run.command('fixel2voxel ' + prefix + 'fixel/directions.mif split_dir ' + prefix + 'all_dirs.mif') file.delTempFolder(prefix + 'fixel') run.command('mrconvert ' + prefix + 'all_dirs.mif ' + prefix + 'first_dir.mif -coord 3 0:2') file.delTempFile(prefix + 'all_dirs.mif') # Revise single-fibre voxel selection based on ratio of tallest to second-tallest peak run.command('mrcalc ' + prefix + 'second_peaks.mif ' + prefix + 'first_peaks.mif -div ' + prefix + 'peak_ratio.mif') file.delTempFile(prefix + 'first_peaks.mif') file.delTempFile(prefix + 'second_peaks.mif') run.command('mrcalc ' + prefix + 'peak_ratio.mif ' + str(app.args.peak_ratio) + ' -lt ' + mask_in_path + ' -mult ' + prefix + 'SF.mif -datatype bit') file.delTempFile(prefix + 'peak_ratio.mif') # Make sure image isn't empty SF_voxel_count = int(image.statistic(prefix + 'SF.mif', 'count', prefix + 'SF.mif')) if not SF_voxel_count: app.error('Aborting: All voxels have been excluded from single-fibre selection') # Generate a new response function run.command('amp2response dwi.mif ' + prefix + 'SF.mif ' + prefix + 'first_dir.mif ' + prefix + 'RF.txt' + lmax_option) file.delTempFile(prefix + 'first_dir.mif') # Detect convergence # Look for a change > some percentage - don't bother looking at the masks if iteration > 0: with open(RF_in_path, 'r') as old_RF_file: old_RF = [ float(x) for x in old_RF_file.read().split() ] with open(prefix + 'RF.txt', 'r') as new_RF_file: new_RF = [ float(x) for x in new_RF_file.read().split() ] reiterate = False for index in range(0, len(old_RF)): mean = 0.5 * (old_RF[index] + new_RF[index]) diff = math.fabs(0.5 * (old_RF[index] - new_RF[index])) ratio = diff / mean if ratio > convergence_change: reiterate = True if not reiterate: app.console('Exiting at iteration ' + str(iteration) + ' with ' + str(SF_voxel_count) + ' SF voxels due to unchanged response function coefficients') run.function(shutil.copyfile, prefix + 'RF.txt', 'response.txt') run.function(shutil.copyfile, prefix + 'SF.mif', 'voxels.mif') break file.delTempFile(RF_in_path) file.delTempFile(mask_in_path) # Go to the next iteration # If we've terminated due to hitting the iteration limiter, we still need to copy the output file(s) to the correct location if not os.path.exists('response.txt'): app.console('Exiting after maximum ' + str(app.args.max_iters-1) + ' iterations with ' + str(SF_voxel_count) + ' SF voxels') run.function(shutil.copyfile, 'iter' + str(app.args.max_iters-1) + '_RF.txt', 'response.txt') run.function(shutil.copyfile, 'iter' + str(app.args.max_iters-1) + '_SF.mif', 'voxels.mif') run.function(shutil.copyfile, 'response.txt', path.fromUser(app.args.output, False))
def execute(): #pylint: disable=unused-variable import math, os from mrtrix3 import app, 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') bet_cmd = fsl.exeName('bet') fast_cmd = fsl.exeName('fast') first_cmd = fsl.exeName('run_first_all') ssroi_cmd = fsl.exeName('standard_space_roi') 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' ]) t1_spacing = image.Header('input.mif').spacing() upsample_for_first = False # If voxel size is 1.25mm or larger, make a guess that the user has erroneously re-gridded their data if math.pow(t1_spacing[0] * t1_spacing[1] * t1_spacing[2], 1.0/3.0) > 1.225: app.warn('Voxel size larger than expected for T1-weighted images (' + str(t1_spacing) + '); ' 'note that ACT does not require re-gridding of T1 image to DWI space, and indeed ' 'retaining the original higher resolution of the T1 image is preferable') upsample_for_first = True run.command('mrconvert input.mif T1.nii -strides -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 -datatype bit') run.command('mrcalc T1.nii mask_regrid.mif -mult ' + 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) pre_bet_image = fsl.findImage('T1_preBET') # BET run.command(bet_cmd + ' ' + pre_bet_image + ' T1_BET' + fsl_suffix + ' -f 0.15 -R') fast_t1_input = fsl.findImage('T1_BET' + fsl_suffix) 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) # FIRST first_input = 'T1.nii' if upsample_for_first: app.warn('Generating 1mm isotropic T1 image for FIRST in hope of preventing failure, since input image is of lower resolution') run.command('mrresize T1.nii T1_1mm.nii -voxel 1.0 -interp sinc') first_input = 'T1_1mm.nii' first_input_brain_extracted_option = '' if app.args.premasked: first_input_brain_extracted_option = ' -b' first_debug_option = '' if not app.cleanup: first_debug_option = ' -d' first_verbosity_option = '' if app.verbosity == 3: first_verbosity_option = ' -v' run.command(first_cmd + ' -m none -s ' + ','.join(sgm_structures) + ' -i ' + first_input + ' -o first' + first_input_brain_extracted_option + first_debug_option + first_verbosity_option) fsl.checkFirst('first', sgm_structures) # Convert FIRST meshes to partial volume images pve_image_list = [ ] progress = app.progressBar('Generating partial volume images for SGM structures', len(sgm_structures)) for struct in sgm_structures: pve_image_path = 'mesh2voxel_' + 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 ' + first_input) run.command('mesh2voxel ' + vtk_temp_path + ' ' + fast_t1_input + ' ' + pve_image_path) pve_image_list.append(pve_image_path) progress.increment() progress.done() run.command('mrmath ' + ' '.join(pve_image_list) + ' sum - | mrcalc - 1.0 -min all_sgms.mif') # Combine the tissue images into the 5TT format within the script itself fast_output_prefix = fast_t1_input.split('.')[0] fast_csf_output = fsl.findImage(fast_output_prefix + '_pve_0') fast_gm_output = fsl.findImage(fast_output_prefix + '_pve_1') fast_wm_output = fsl.findImage(fast_output_prefix + '_pve_2') # Step 1: Run LCC on the WM image run.command('mrthreshold ' + fast_wm_output + ' - -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 old 5ttgen binary used to: # - Preserve CSF as-is # - Preserve SGM, unless it results in a sum of volume fractions greater than 1, in which case clamp # - Multiply the FAST volume fractions of GM and CSF, so that the sum of CSF, SGM, CGM and WM is 1.0 run.command('mrcalc ' + fast_csf_output + ' 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_gm_output + ' ' + fast_wm_output + ' -add -div multiplier.mif') run.command('mrcalc multiplier.mif -finite multiplier.mif 0.0 -if multiplier_noNAN.mif') run.command('mrcalc ' + fast_gm_output + ' multiplier_noNAN.mif -mult remove_unconnected_wm_mask.mif -mult cgm.mif') run.command('mrcalc ' + fast_wm_output + ' 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 -strides +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 -')
def execute(): #pylint: disable=unused-variable bzero_threshold = float( CONFIG['BZeroThreshold']) if 'BZeroThreshold' in CONFIG else 10.0 # CHECK INPUTS AND OPTIONS app.console('-------') # Get b-values and number of volumes per b-value. bvalues = [ int(round(float(x))) for x in image.mrinfo('dwi.mif', 'shell_bvalues').split() ] bvolumes = [int(x) for x in image.mrinfo('dwi.mif', 'shell_sizes').split()] app.console( str(len(bvalues)) + ' unique b-value(s) detected: ' + ','.join(map(str, bvalues)) + ' with ' + ','.join(map(str, bvolumes)) + ' volumes') if len(bvalues) < 2: raise MRtrixError('Need at least 2 unique b-values (including b=0).') bvalues_option = ' -shells ' + ','.join(map(str, bvalues)) # Get lmax information (if provided). sfwm_lmax = [] if app.ARGS.lmax: sfwm_lmax = [int(x.strip()) for x in app.ARGS.lmax.split(',')] if not len(sfwm_lmax) == len(bvalues): raise MRtrixError('Number of lmax\'s (' + str(len(sfwm_lmax)) + ', as supplied to the -lmax option: ' + ','.join(map(str, sfwm_lmax)) + ') does not match number of unique b-values.') for sfl in sfwm_lmax: if sfl % 2: raise MRtrixError( 'Values supplied to the -lmax option must be even.') if sfl < 0: raise MRtrixError( 'Values supplied to the -lmax option must be non-negative.' ) sfwm_lmax_option = '' if sfwm_lmax: sfwm_lmax_option = ' -lmax ' + ','.join(map(str, sfwm_lmax)) # PREPARATION app.console('-------') app.console('Preparation:') # Erode (brain) mask. if app.ARGS.erode > 0: app.console('* Eroding brain mask by ' + str(app.ARGS.erode) + ' pass(es)...') run.command('maskfilter mask.mif erode eroded_mask.mif -npass ' + str(app.ARGS.erode), show=False) else: app.console('Not eroding brain mask.') run.command('mrconvert mask.mif eroded_mask.mif -datatype bit', show=False) statmaskcount = image.statistics('mask.mif', mask='mask.mif').count statemaskcount = image.statistics('eroded_mask.mif', mask='eroded_mask.mif').count app.console(' [ mask: ' + str(statmaskcount) + ' -> ' + str(statemaskcount) + ' ]') # Get volumes, compute mean signal and SDM per b-value; compute overall SDM; get rid of erroneous values. app.console('* Computing signal decay metric (SDM):') totvolumes = 0 fullsdmcmd = 'mrcalc' errcmd = 'mrcalc' zeropath = 'mean_b' + str(bvalues[0]) + '.mif' for ibv, bval in enumerate(bvalues): app.console(' * b=' + str(bval) + '...') meanpath = 'mean_b' + str(bval) + '.mif' run.command('dwiextract dwi.mif -shells ' + str(bval) + ' - | mrcalc - 0 -max - | mrmath - mean ' + meanpath + ' -axis 3', show=False) errpath = 'err_b' + str(bval) + '.mif' run.command('mrcalc ' + meanpath + ' -finite ' + meanpath + ' 0 -if 0 -le ' + errpath + ' -datatype bit', show=False) errcmd += ' ' + errpath if ibv > 0: errcmd += ' -add' sdmpath = 'sdm_b' + str(bval) + '.mif' run.command('mrcalc ' + zeropath + ' ' + meanpath + ' -divide -log ' + sdmpath, show=False) totvolumes += bvolumes[ibv] fullsdmcmd += ' ' + sdmpath + ' ' + str(bvolumes[ibv]) + ' -mult' if ibv > 1: fullsdmcmd += ' -add' fullsdmcmd += ' ' + str(totvolumes) + ' -divide full_sdm.mif' run.command(fullsdmcmd, show=False) app.console('* Removing erroneous voxels from mask and correcting SDM...') run.command( 'mrcalc full_sdm.mif -finite full_sdm.mif 0 -if 0 -le err_sdm.mif -datatype bit', show=False) errcmd += ' err_sdm.mif -add 0 eroded_mask.mif -if safe_mask.mif -datatype bit' run.command(errcmd, show=False) run.command('mrcalc safe_mask.mif full_sdm.mif 0 -if 10 -min safe_sdm.mif', show=False) statsmaskcount = image.statistics('safe_mask.mif', mask='safe_mask.mif').count app.console(' [ mask: ' + str(statemaskcount) + ' -> ' + str(statsmaskcount) + ' ]') # CRUDE SEGMENTATION app.console('-------') app.console('Crude segmentation:') # Compute FA and principal eigenvectors; crude WM versus GM-CSF separation based on FA. app.console('* Crude WM versus GM-CSF separation (at FA=' + str(app.ARGS.fa) + ')...') run.command( 'dwi2tensor dwi.mif - -mask safe_mask.mif | tensor2metric - -fa safe_fa.mif -vector safe_vecs.mif -modulate none -mask safe_mask.mif', show=False) run.command('mrcalc safe_mask.mif safe_fa.mif 0 -if ' + str(app.ARGS.fa) + ' -gt crude_wm.mif -datatype bit', show=False) run.command( 'mrcalc crude_wm.mif 0 safe_mask.mif -if _crudenonwm.mif -datatype bit', show=False) statcrudewmcount = image.statistics('crude_wm.mif', mask='crude_wm.mif').count statcrudenonwmcount = image.statistics('_crudenonwm.mif', mask='_crudenonwm.mif').count app.console(' [ ' + str(statsmaskcount) + ' -> ' + str(statcrudewmcount) + ' (WM) & ' + str(statcrudenonwmcount) + ' (GM-CSF) ]') # Crude GM versus CSF separation based on SDM. app.console('* Crude GM versus CSF separation...') crudenonwmmedian = image.statistics('safe_sdm.mif', mask='_crudenonwm.mif').median run.command( 'mrcalc _crudenonwm.mif safe_sdm.mif ' + str(crudenonwmmedian) + ' -subtract 0 -if - | mrthreshold - - -mask _crudenonwm.mif | mrcalc _crudenonwm.mif - 0 -if crude_csf.mif -datatype bit', show=False) run.command( 'mrcalc crude_csf.mif 0 _crudenonwm.mif -if crude_gm.mif -datatype bit', show=False) statcrudegmcount = image.statistics('crude_gm.mif', mask='crude_gm.mif').count statcrudecsfcount = image.statistics('crude_csf.mif', mask='crude_csf.mif').count app.console(' [ ' + str(statcrudenonwmcount) + ' -> ' + str(statcrudegmcount) + ' (GM) & ' + str(statcrudecsfcount) + ' (CSF) ]') # REFINED SEGMENTATION app.console('-------') app.console('Refined segmentation:') # Refine WM: remove high SDM outliers. app.console('* Refining WM...') crudewmmedian = image.statistics('safe_sdm.mif', mask='crude_wm.mif').median run.command('mrcalc crude_wm.mif safe_sdm.mif ' + str(crudewmmedian) + ' -subtract -abs 0 -if _crudewm_sdmad.mif', show=False) crudewmmad = image.statistics('_crudewm_sdmad.mif', mask='crude_wm.mif').median crudewmoutlthresh = crudewmmedian + (1.4826 * crudewmmad * 2.0) run.command('mrcalc crude_wm.mif safe_sdm.mif 0 -if ' + str(crudewmoutlthresh) + ' -gt _crudewmoutliers.mif -datatype bit', show=False) run.command( 'mrcalc _crudewmoutliers.mif 0 crude_wm.mif -if refined_wm.mif -datatype bit', show=False) statrefwmcount = image.statistics('refined_wm.mif', mask='refined_wm.mif').count app.console(' [ WM: ' + str(statcrudewmcount) + ' -> ' + str(statrefwmcount) + ' ]') # Refine GM: separate safer GM from partial volumed voxels. app.console('* Refining GM...') crudegmmedian = image.statistics('safe_sdm.mif', mask='crude_gm.mif').median run.command('mrcalc crude_gm.mif safe_sdm.mif 0 -if ' + str(crudegmmedian) + ' -gt _crudegmhigh.mif -datatype bit', show=False) run.command( 'mrcalc _crudegmhigh.mif 0 crude_gm.mif -if _crudegmlow.mif -datatype bit', show=False) run.command( 'mrcalc _crudegmhigh.mif safe_sdm.mif ' + str(crudegmmedian) + ' -subtract 0 -if - | mrthreshold - - -mask _crudegmhigh.mif -invert | mrcalc _crudegmhigh.mif - 0 -if _crudegmhighselect.mif -datatype bit', show=False) run.command( 'mrcalc _crudegmlow.mif safe_sdm.mif ' + str(crudegmmedian) + ' -subtract -neg 0 -if - | mrthreshold - - -mask _crudegmlow.mif -invert | mrcalc _crudegmlow.mif - 0 -if _crudegmlowselect.mif -datatype bit', show=False) run.command( 'mrcalc _crudegmhighselect.mif 1 _crudegmlowselect.mif -if refined_gm.mif -datatype bit', show=False) statrefgmcount = image.statistics('refined_gm.mif', mask='refined_gm.mif').count app.console(' [ GM: ' + str(statcrudegmcount) + ' -> ' + str(statrefgmcount) + ' ]') # Refine CSF: recover lost CSF from crude WM SDM outliers, separate safer CSF from partial volumed voxels. app.console('* Refining CSF...') crudecsfmin = image.statistics('safe_sdm.mif', mask='crude_csf.mif').min run.command('mrcalc _crudewmoutliers.mif safe_sdm.mif 0 -if ' + str(crudecsfmin) + ' -gt 1 crude_csf.mif -if _crudecsfextra.mif -datatype bit', show=False) run.command( 'mrcalc _crudecsfextra.mif safe_sdm.mif ' + str(crudecsfmin) + ' -subtract 0 -if - | mrthreshold - - -mask _crudecsfextra.mif | mrcalc _crudecsfextra.mif - 0 -if refined_csf.mif -datatype bit', show=False) statrefcsfcount = image.statistics('refined_csf.mif', mask='refined_csf.mif').count app.console(' [ CSF: ' + str(statcrudecsfcount) + ' -> ' + str(statrefcsfcount) + ' ]') # FINAL VOXEL SELECTION AND RESPONSE FUNCTION ESTIMATION app.console('-------') app.console('Final voxel selection and response function estimation:') # Get final voxels for CSF response function estimation from refined CSF. app.console('* CSF:') app.console(' * Selecting final voxels (' + str(app.ARGS.csf) + '% of refined CSF)...') voxcsfcount = int(round(statrefcsfcount * app.ARGS.csf / 100.0)) run.command( 'mrcalc refined_csf.mif safe_sdm.mif 0 -if - | mrthreshold - - -top ' + str(voxcsfcount) + ' -ignorezero | mrcalc refined_csf.mif - 0 -if - -datatype bit | mrconvert - voxels_csf.mif -axes 0,1,2', show=False) statvoxcsfcount = image.statistics('voxels_csf.mif', mask='voxels_csf.mif').count app.console(' [ CSF: ' + str(statrefcsfcount) + ' -> ' + str(statvoxcsfcount) + ' ]') # Estimate CSF response function app.console(' * Estimating response function...') run.command( 'amp2response dwi.mif voxels_csf.mif safe_vecs.mif response_csf.txt' + bvalues_option + ' -isotropic', show=False) # Get final voxels for GM response function estimation from refined GM. app.console('* GM:') app.console(' * Selecting final voxels (' + str(app.ARGS.gm) + '% of refined GM)...') voxgmcount = int(round(statrefgmcount * app.ARGS.gm / 100.0)) refgmmedian = image.statistics('safe_sdm.mif', mask='refined_gm.mif').median run.command( 'mrcalc refined_gm.mif safe_sdm.mif ' + str(refgmmedian) + ' -subtract -abs 1 -add 0 -if - | mrthreshold - - -bottom ' + str(voxgmcount) + ' -ignorezero | mrcalc refined_gm.mif - 0 -if - -datatype bit | mrconvert - voxels_gm.mif -axes 0,1,2', show=False) statvoxgmcount = image.statistics('voxels_gm.mif', mask='voxels_gm.mif').count app.console(' [ GM: ' + str(statrefgmcount) + ' -> ' + str(statvoxgmcount) + ' ]') # Estimate GM response function app.console(' * Estimating response function...') run.command( 'amp2response dwi.mif voxels_gm.mif safe_vecs.mif response_gm.txt' + bvalues_option + ' -isotropic', show=False) # Get final voxels for single-fibre WM response function estimation from refined WM. app.console('* Single-fibre WM:') app.console(' * Selecting final voxels' + ('' if app.ARGS.wm_algo == 'tax' else (' (' + str(app.ARGS.sfwm) + '% of refined WM)')) + '...') voxsfwmcount = int(round(statrefwmcount * app.ARGS.sfwm / 100.0)) if app.ARGS.wm_algo: recursive_cleanup_option = '' if not app.DO_CLEANUP: recursive_cleanup_option = ' -nocleanup' app.console(' Selecting WM single-fibre voxels using \'' + app.ARGS.wm_algo + '\' algorithm') if app.ARGS.wm_algo == 'tax' and app.ARGS.sfwm != 0.5: app.warn( 'Single-fibre WM response function selection algorithm "tax" will not honour requested WM voxel percentage' ) run.command( 'dwi2response ' + app.ARGS.wm_algo + ' dwi.mif _respsfwmss.txt -mask refined_wm.mif -voxels voxels_sfwm.mif' + ('' if app.ARGS.wm_algo == 'tax' else (' -number ' + str(voxsfwmcount))) + ' -scratch ' + path.quote(app.SCRATCH_DIR) + recursive_cleanup_option, show=False) else: app.console( ' Selecting WM single-fibre voxels using built-in (Dhollander et al., 2019) algorithm' ) run.command('mrmath dwi.mif mean mean_sig.mif -axis 3', show=False) refwmcoef = image.statistics('mean_sig.mif', mask='refined_wm.mif').median * math.sqrt( 4.0 * math.pi) if sfwm_lmax: isiso = [lm == 0 for lm in sfwm_lmax] else: isiso = [bv < bzero_threshold for bv in bvalues] with open('ewmrf.txt', 'w') as ewr: for iis in isiso: if iis: ewr.write("%s 0 0 0\n" % refwmcoef) else: ewr.write("%s -%s %s -%s\n" % (refwmcoef, refwmcoef, refwmcoef, refwmcoef)) run.command( 'dwi2fod msmt_csd dwi.mif ewmrf.txt abs_ewm2.mif response_csf.txt abs_csf2.mif -mask refined_wm.mif -lmax 2,0' + bvalues_option, show=False) run.command( 'mrconvert abs_ewm2.mif - -coord 3 0 | mrcalc - abs_csf2.mif -add abs_sum2.mif', show=False) run.command( 'sh2peaks abs_ewm2.mif - -num 1 -mask refined_wm.mif | peaks2amp - - | mrcalc - abs_sum2.mif -divide - | mrconvert - metric_sfwm2.mif -coord 3 0 -axes 0,1,2', show=False) run.command( 'mrcalc refined_wm.mif metric_sfwm2.mif 0 -if - | mrthreshold - - -top ' + str(voxsfwmcount * 2) + ' -ignorezero | mrcalc refined_wm.mif - 0 -if - -datatype bit | mrconvert - refined_sfwm.mif -axes 0,1,2', show=False) run.command( 'dwi2fod msmt_csd dwi.mif ewmrf.txt abs_ewm6.mif response_csf.txt abs_csf6.mif -mask refined_sfwm.mif -lmax 6,0' + bvalues_option, show=False) run.command( 'mrconvert abs_ewm6.mif - -coord 3 0 | mrcalc - abs_csf6.mif -add abs_sum6.mif', show=False) run.command( 'sh2peaks abs_ewm6.mif - -num 1 -mask refined_sfwm.mif | peaks2amp - - | mrcalc - abs_sum6.mif -divide - | mrconvert - metric_sfwm6.mif -coord 3 0 -axes 0,1,2', show=False) run.command( 'mrcalc refined_sfwm.mif metric_sfwm6.mif 0 -if - | mrthreshold - - -top ' + str(voxsfwmcount) + ' -ignorezero | mrcalc refined_sfwm.mif - 0 -if - -datatype bit | mrconvert - voxels_sfwm.mif -axes 0,1,2', show=False) statvoxsfwmcount = image.statistics('voxels_sfwm.mif', mask='voxels_sfwm.mif').count app.console(' [ WM: ' + str(statrefwmcount) + ' -> ' + str(statvoxsfwmcount) + ' (single-fibre) ]') # Estimate SF WM response function app.console(' * Estimating response function...') run.command( 'amp2response dwi.mif voxels_sfwm.mif safe_vecs.mif response_sfwm.txt' + bvalues_option + sfwm_lmax_option, show=False) # OUTPUT AND SUMMARY app.console('-------') app.console('Generating outputs...') # Generate 4D binary images with voxel selections at major stages in algorithm (RGB: WM=blue, GM=green, CSF=red). run.command( 'mrcat crude_csf.mif crude_gm.mif crude_wm.mif check_crude.mif -axis 3', show=False) run.command( 'mrcat refined_csf.mif refined_gm.mif refined_wm.mif check_refined.mif -axis 3', show=False) run.command( 'mrcat voxels_csf.mif voxels_gm.mif voxels_sfwm.mif check_voxels.mif -axis 3', show=False) # Copy results to output files run.function(shutil.copyfile, 'response_sfwm.txt', path.from_user(app.ARGS.out_sfwm, False), show=False) run.function(shutil.copyfile, 'response_gm.txt', path.from_user(app.ARGS.out_gm, False), show=False) run.function(shutil.copyfile, 'response_csf.txt', path.from_user(app.ARGS.out_csf, False), show=False) if app.ARGS.voxels: run.command('mrconvert check_voxels.mif ' + path.from_user(app.ARGS.voxels), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE, show=False) app.console('-------')
def execute(): import math, os, shutil from mrtrix3 import app, image, path, run # Ideally want to use the oversampling-based regridding of the 5TT image from the SIFT model, not mrtransform # May need to commit 5ttregrid... # Verify input 5tt image run.command('5ttcheck 5tt.mif', False) # Get shell information shells = [ int(round(float(x))) for x in image.headerField('dwi.mif', 'shells').split() ] if len(shells) < 3: app.warn('Less than three b-value shells; response functions will not be applicable in resolving three tissues using MSMT-CSD algorithm') # Get lmax information (if provided) wm_lmax = [ ] if app.args.lmax: wm_lmax = [ int(x.strip()) for x in app.args.lmax.split(',') ] if not len(wm_lmax) == len(shells): app.error('Number of manually-defined lmax\'s (' + str(len(wm_lmax)) + ') does not match number of b-value shells (' + str(len(shells)) + ')') for l in wm_lmax: if l%2: app.error('Values for lmax must be even') if l<0: app.error('Values for lmax must be non-negative') run.command('dwi2tensor dwi.mif - -mask mask.mif | tensor2metric - -fa fa.mif -vector vector.mif') if not os.path.exists('dirs.mif'): run.function(shutil.copy, 'vector.mif', 'dirs.mif') run.command('mrtransform 5tt.mif 5tt_regrid.mif -template fa.mif -interp linear') # Basic tissue masks run.command('mrconvert 5tt_regrid.mif - -coord 3 2 -axes 0,1,2 | mrcalc - ' + str(app.args.pvf) + ' -gt mask.mif -mult wm_mask.mif') run.command('mrconvert 5tt_regrid.mif - -coord 3 0 -axes 0,1,2 | mrcalc - ' + str(app.args.pvf) + ' -gt fa.mif ' + str(app.args.fa) + ' -lt -mult mask.mif -mult gm_mask.mif') run.command('mrconvert 5tt_regrid.mif - -coord 3 3 -axes 0,1,2 | mrcalc - ' + str(app.args.pvf) + ' -gt fa.mif ' + str(app.args.fa) + ' -lt -mult mask.mif -mult csf_mask.mif') # Revise WM mask to only include single-fibre voxels app.console('Calling dwi2response recursively to select WM single-fibre voxels using \'' + app.args.wm_algo + '\' algorithm') recursive_cleanup_option='' if not app._cleanup: recursive_cleanup_option = ' -nocleanup' run.command('dwi2response ' + app.args.wm_algo + ' dwi.mif wm_ss_response.txt -mask wm_mask.mif -voxels wm_sf_mask.mif -tempdir ' + app._tempDir + recursive_cleanup_option) # Check for empty masks wm_voxels = int(image.statistic('wm_sf_mask.mif', 'count', 'wm_sf_mask.mif')) gm_voxels = int(image.statistic('gm_mask.mif', 'count', 'gm_mask.mif')) csf_voxels = int(image.statistic('csf_mask.mif', 'count', 'csf_mask.mif')) empty_masks = [ ] if not wm_voxels: empty_masks.append('WM') if not gm_voxels: empty_masks.append('GM') if not csf_voxels: empty_masks.append('CSF') if empty_masks: message = ','.join(empty_masks) message += ' tissue mask' if len(empty_masks) > 1: message += 's' message += ' empty; cannot estimate response function' if len(empty_masks) > 1: message += 's' app.error(message) # For each of the three tissues, generate a multi-shell response bvalues_option = ' -shell ' + ','.join(map(str,shells)) sfwm_lmax_option = '' if wm_lmax: sfwm_lmax_option = ' -lmax ' + ','.join(map(str,wm_lmax)) run.command('amp2response dwi.mif wm_sf_mask.mif dirs.mif wm.txt' + bvalues_option + sfwm_lmax_option) run.command('amp2response dwi.mif gm_mask.mif dirs.mif gm.txt' + bvalues_option + ' -isotropic') run.command('amp2response dwi.mif csf_mask.mif dirs.mif csf.txt' + bvalues_option + ' -isotropic') run.function(shutil.copyfile, 'wm.txt', path.fromUser(app.args.out_wm, False)) run.function(shutil.copyfile, 'gm.txt', path.fromUser(app.args.out_gm, False)) run.function(shutil.copyfile, 'csf.txt', path.fromUser(app.args.out_csf, False)) # Generate output 4D binary image with voxel selections; RGB as in MSMT-CSD paper run.command('mrcat csf_mask.mif gm_mask.mif wm_sf_mask.mif voxels.mif -axis 3')
def execute(): import os, shutil from mrtrix3 import app, image, path, run bvalues = [ int(round(float(x))) for x in image.headerField('dwi.mif', 'shells').split() ] if len(bvalues) < 2: app.error('Need at least 2 unique b-values (including b=0).') lmax_option = '' if app.args.lmax: lmax_option = ' -lmax ' + app.args.lmax if not app.args.mask: run.command('maskfilter mask.mif erode mask_eroded.mif -npass ' + str(app.args.erode)) mask_path = 'mask_eroded.mif' else: mask_path = 'mask.mif' run.command('dwi2tensor dwi.mif -mask ' + mask_path + ' tensor.mif') run.command('tensor2metric tensor.mif -fa fa.mif -vector vector.mif -mask ' + mask_path) if app.args.threshold: run.command('mrthreshold fa.mif voxels.mif -abs ' + str(app.args.threshold)) else: run.command('mrthreshold fa.mif voxels.mif -top ' + str(app.args.number)) run.command('dwiextract dwi.mif - -singleshell -no_bzero | amp2response - voxels.mif vector.mif response.txt' + lmax_option) run.function(shutil.copyfile, 'response.txt', path.fromUser(app.args.output, False))
def get_inputs(): #pylint: disable=unused-variable run.command('mrconvert ' + path.from_user(app.ARGS.input) + ' ' + path.to_scratch('input.mif')) if app.ARGS.lut: run.function(shutil.copyfile, path.from_user(app.ARGS.lut, False), path.to_scratch('LUT.txt', False))
def execute(): import os, sys from mrtrix3 import app, path, run lut_input_path = 'LUT.txt' if not os.path.exists('LUT.txt'): freesurfer_home = os.environ.get('FREESURFER_HOME', '') if not freesurfer_home: app.error( 'Environment variable FREESURFER_HOME is not set; please run appropriate FreeSurfer configuration script, set this variable manually, or provide script with path to file FreeSurferColorLUT.txt using -lut option' ) lut_input_path = os.path.join(freesurfer_home, 'FreeSurferColorLUT.txt') if not os.path.isfile(lut_input_path): app.error( 'Could not find FreeSurfer lookup table file (expected location: ' + freesurfer_lut + '), and none provided using -lut') if app.args.sgm_amyg_hipp: lut_output_file_name = 'FreeSurfer2ACT_sgm_amyg_hipp.txt' else: lut_output_file_name = 'FreeSurfer2ACT.txt' lut_output_path = os.path.join(path.sharedDataPath(), path.scriptSubDirName(), lut_output_file_name) if not os.path.isfile(lut_output_path): app.error( 'Could not find lookup table file for converting FreeSurfer parcellation output to tissues (expected location: ' + lut_output_path + ')') # Initial conversion from FreeSurfer parcellation to five principal tissue types run.command('labelconvert input.mif ' + lut_input_path + ' ' + lut_output_path + ' indices.mif') # Use mrcrop to reduce file size if app.args.nocrop: image = 'indices.mif' else: image = 'indices_cropped.mif' run.command( 'mrthreshold indices.mif - -abs 0.5 | mrcrop indices.mif ' + image + ' -mask -') # Convert into the 5TT format for ACT run.command('mrcalc ' + image + ' 1 -eq cgm.mif') run.command('mrcalc ' + image + ' 2 -eq sgm.mif') run.command('mrcalc ' + image + ' 3 -eq wm.mif') run.command('mrcalc ' + image + ' 4 -eq csf.mif') run.command('mrcalc ' + image + ' 5 -eq path.mif') run.command( 'mrcat cgm.mif sgm.mif wm.mif csf.mif path.mif - -axis 3 | mrconvert - result.mif -datatype float32' )
# DW gradient files grad_prefix = os.path.join(app.args.in_dir, label, 'dwi', label + '_dwi') if not (os.path.isfile(grad_prefix + '.bval') and os.path.isfile(grad_prefix + '.bvec')): grad_prefix = os.path.join(app.args.in_dir, 'dwi') if not (os.path.isfile(grad_prefix + '.bval') and os.path.isfile(grad_prefix + '.bvec')): app.error('Unable to locate valid diffusion gradient table') grad_import_option = ' -fslgrad ' + grad_prefix + '.bvec ' + grad_prefix + '.bval' # Stuff DWI gradients in *.mif file print('mrconvert ' + all_dwi_images[0] + grad_import_option + ' ' + dwi_preproc_file) run.command('mrconvert ' + all_dwi_images[0] + grad_import_option + ' ' + dwi_preproc_file + ' -force') print(' problem here? ') # Compute brain mask run.command('dwi2mask ' + dwi_preproc_file + ' ' + output_mask + ' -force') # Perform Bias Correction run.command('dwibiascorrect ' + '-ants ' + '-mask ' + output_mask + ' ' + dwi_preproc_file + ' ' + dwi_bias_file + ' -force') # running group level 1 (perform intensity normalisation, calculate response functions, average response ) elif app.args.analysis_level == "group1": print('performing intensity normalisation') intensitynorm_output = os.path.join(template_dir, 'inorm_output')
def execute(): #pylint: disable=unused-variable import os, shutil from mrtrix3 import app, file, image, path, run #pylint: disable=redefined-builtin lmax_option = '' if app.args.lmax: lmax_option = ' -lmax ' + app.args.lmax if app.args.max_iters < 2: app.error('Number of iterations must be at least 2') for iteration in range(0, app.args.max_iters): prefix = 'iter' + str(iteration) + '_' if iteration == 0: RF_in_path = 'init_RF.txt' mask_in_path = 'mask.mif' init_RF = '1 -1 1' with open(RF_in_path, 'w') as f: f.write(init_RF) iter_lmax_option = ' -lmax 4' else: RF_in_path = 'iter' + str(iteration-1) + '_RF.txt' mask_in_path = 'iter' + str(iteration-1) + '_SF_dilated.mif' iter_lmax_option = lmax_option # Run CSD run.command('dwi2fod csd dwi.mif ' + RF_in_path + ' ' + prefix + 'FOD.mif -mask ' + mask_in_path + iter_lmax_option) # Get amplitudes of two largest peaks, and direction of largest run.command('fod2fixel ' + prefix + 'FOD.mif ' + prefix + 'fixel -peak peaks.mif -mask ' + mask_in_path + ' -fmls_no_thresholds') file.delTemporary(prefix + 'FOD.mif') if iteration: file.delTemporary(mask_in_path) run.command('fixel2voxel ' + prefix + 'fixel/peaks.mif split_data ' + prefix + 'amps.mif -number 2') run.command('mrconvert ' + prefix + 'amps.mif ' + prefix + 'first_peaks.mif -coord 3 0 -axes 0,1,2') run.command('mrconvert ' + prefix + 'amps.mif ' + prefix + 'second_peaks.mif -coord 3 1 -axes 0,1,2') file.delTemporary(prefix + 'amps.mif') run.command('fixel2voxel ' + prefix + 'fixel/directions.mif split_dir ' + prefix + 'all_dirs.mif -number 1') file.delTemporary(prefix + 'fixel') run.command('mrconvert ' + prefix + 'all_dirs.mif ' + prefix + 'first_dir.mif -coord 3 0:2') file.delTemporary(prefix + 'all_dirs.mif') # Calculate the 'cost function' Donald derived for selecting single-fibre voxels # https://github.com/MRtrix3/mrtrix3/pull/426 # sqrt(|peak1|) * (1 - |peak2| / |peak1|)^2 run.command('mrcalc ' + prefix + 'first_peaks.mif -sqrt 1 ' + prefix + 'second_peaks.mif ' + prefix + 'first_peaks.mif -div -sub 2 -pow -mult '+ prefix + 'CF.mif') file.delTemporary(prefix + 'first_peaks.mif') file.delTemporary(prefix + 'second_peaks.mif') # Select the top-ranked voxels run.command('mrthreshold ' + prefix + 'CF.mif -top ' + str(app.args.sf_voxels) + ' ' + prefix + 'SF.mif') # Generate a new response function based on this selection run.command('amp2response dwi.mif ' + prefix + 'SF.mif ' + prefix + 'first_dir.mif ' + prefix + 'RF.txt' + iter_lmax_option) file.delTemporary(prefix + 'first_dir.mif') # Should we terminate? if iteration > 0: run.command('mrcalc ' + prefix + 'SF.mif iter' + str(iteration-1) + '_SF.mif -sub ' + prefix + 'SF_diff.mif') file.delTemporary('iter' + str(iteration-1) + '_SF.mif') max_diff = image.statistic(prefix + 'SF_diff.mif', 'max') file.delTemporary(prefix + 'SF_diff.mif') if int(max_diff) == 0: app.console('Convergence of SF voxel selection detected at iteration ' + str(iteration)) file.delTemporary(prefix + 'CF.mif') run.function(shutil.copyfile, prefix + 'RF.txt', 'response.txt') run.function(shutil.move, prefix + 'SF.mif', 'voxels.mif') break # Select a greater number of top single-fibre voxels, and dilate (within bounds of initial mask); # these are the voxels that will be re-tested in the next iteration run.command('mrthreshold ' + prefix + 'CF.mif -top ' + str(app.args.iter_voxels) + ' - | maskfilter - dilate - -npass ' + str(app.args.dilate) + ' | mrcalc mask.mif - -mult ' + prefix + 'SF_dilated.mif') file.delTemporary(prefix + 'CF.mif') # Commence the next iteration # If terminating due to running out of iterations, still need to put the results in the appropriate location if not os.path.exists('response.txt'): app.console('Exiting after maximum ' + str(app.args.max_iters) + ' iterations') run.function(shutil.copyfile, 'iter' + str(app.args.max_iters-1) + '_RF.txt', 'response.txt') run.function(shutil.move, 'iter' + str(app.args.max_iters-1) + '_SF.mif', 'voxels.mif') run.function(shutil.copyfile, 'response.txt', path.fromUser(app.args.output, False))
def get_inputs(): #pylint: disable=unused-variable check_gif_input(path.from_user(app.ARGS.input, False)) run.command('mrconvert ' + path.from_user(app.ARGS.input) + ' ' + path.to_scratch('input.mif'))
def command(self, cmd): from mrtrix3 import run #pylint: disable=import-outside-toplevel assert self.valid run.command(cmd) self._increment()
def getInputs(): #pylint: disable=unused-variable import shutil from mrtrix3 import app, path, run run.command('mrconvert ' + path.fromUser(app.args.input, True) + ' ' + path.toTemp('input.mif', True)) if app.args.lut: run.function(shutil.copyfile, path.fromUser(app.args.lut, False), path.toTemp('LUT.txt', False))
dwi_ind_size = [[0,0,0,0]] if not app.args.fslbval: bvallist = [i + '.bval' for i in DWInlist] else: UserBvalpath = app.args.fslbval.rsplit(',') bvallist = [os.path.realpath(i) for i in UserBvalpath] if not app.args.fslbvec: bveclist = [i + '.bvec' for i in DWInlist] else: UserBvecpath = app.args.fslbvec.rsplit(',') bveclist = [os.path.realpath(i) for i in UserBvecpath] if len(DWInlist) == 1: if not isdicom: run.command('mrconvert -stride -1,2,3,4 -fslgrad ' + bveclist[0] + ' ' + bvallist[0] + ' ' + ''.join(DWInlist) + ''.join(DWIext) + ' ' + path.toTemp('dwi.mif',True)) else: run.command('mrconvert -stride -1,2,3,4 ' + ''.join(DWInlist) + ' ' + path.toTemp('dwi.mif',True)) else: for idx,i in enumerate(DWInlist): if not isdicom: run.command('mrconvert -stride -1,2,3,4 -fslgrad ' + bveclist[idx] + ' ' + bvallist[idx] + ' ' + i + DWIext[idx] + ' ' + path.toTemp('dwi' + str(idx) + '.mif',True)) else: run.command('mrconvert -stride -1,2,3,4 ' + i + ' ' + path.toTemp('dwi' + str(idx) + '.mif',True)) dwi_header = image.Header(path.toTemp('dwi' + str(idx) + '.mif',True)) dwi_ind_size.append([ int(s) for s in dwi_header.size() ]) miflist.append(path.toTemp('dwi' + str(idx) + '.mif',True)) DWImif = ' '.join(miflist) run.command('mrcat -axis 3 ' + DWImif + ' ' + path.toTemp('dwi.mif',True)) app.gotoTempDir()
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 -' )
def execute(): #pylint: disable=unused-variable import shutil from mrtrix3 import app, image, path, run bvalues = [ int(round(float(x))) for x in image.mrinfo('dwi.mif', 'shell_bvalues').split() ] if len(bvalues) < 2: app.error('Need at least 2 unique b-values (including b=0).') lmax_option = '' if app.args.lmax: lmax_option = ' -lmax ' + app.args.lmax if not app.args.mask: run.command('maskfilter mask.mif erode mask_eroded.mif -npass ' + str(app.args.erode)) mask_path = 'mask_eroded.mif' else: mask_path = 'mask.mif' run.command('dwi2tensor dwi.mif -mask ' + mask_path + ' tensor.mif') run.command('tensor2metric tensor.mif -fa fa.mif -vector vector.mif -mask ' + mask_path) if app.args.threshold: run.command('mrthreshold fa.mif voxels.mif -abs ' + str(app.args.threshold)) else: run.command('mrthreshold fa.mif voxels.mif -top ' + str(app.args.number)) run.command('dwiextract dwi.mif - -singleshell -no_bzero | amp2response - voxels.mif vector.mif response.txt' + lmax_option) run.function(shutil.copyfile, 'response.txt', path.fromUser(app.args.output, False))
def execute(): import os, sys from mrtrix3 import app, path, run lut_input_path = 'LUT.txt' if not os.path.exists('LUT.txt'): gif3_home = os.environ.get('GIFDB_HOME', '') if not gif3_home: app.error( 'Environment variable GIFDB_HOME is not set. Please set this variable manually, or provide script with path to file GIF3ColourLUT.txt using -lut option.' ) lut_input_path = os.path.join(gif_home, 'GIF3ColourLUT.txt') if not os.path.isfile(lut_input_path): app.error( 'Could not find GIF3 lookup table file (expected location: ' + lut_input_path + '), and none provided using -lut') if app.args.sgm_amyg_hipp: lut_output_file_name = 'GIF32ACT_sgm_amyg_hipp.txt' else: lut_output_file_name = 'GIF32ACT.txt' lut_output_path = os.path.join(path.sharedDataPath(), path.scriptSubDirName(), lut_output_file_name) if not os.path.isfile(lut_output_path): app.error( 'Could not find lookup table file for converting GIF3 parcellation output to tissues (expected location: ' + lut_output_path + ')') # Initial conversion from GIF3 parcellation to five principal tissue types run.command('labelconvert input.mif ' + lut_input_path + ' ' + lut_output_path + ' indices.mif') # Use mrcrop to reduce file size if app.args.nocrop: image = 'indices.mif' else: image = 'indices_cropped.mif' run.command( 'mrthreshold indices.mif - -abs 0.5 | mrcrop indices.mif ' + image + ' -mask -') # Convert into the 5TT format for ACT run.command('mrcalc ' + image + ' 1 -eq cgm.mif') run.command('mrcalc ' + image + ' 2 -eq sgm.mif') run.command('mrcalc ' + image + ' 3 -eq wm.mif') run.command('mrcalc ' + image + ' 4 -eq csf.mif') run.command('mrcalc ' + image + ' 5 -eq path.mif') run.command( 'mrcat cgm.mif sgm.mif wm.mif csf.mif path.mif - -axis 3 | mrconvert - result.mif -datatype float32' ) # Created by Neil Oxtoby on 2018-03-02 # Modified from freesurfer.py in MRtrix3 v3.0
print('42 is the answer') else: print('this is wrong') for subject in subjects : os.chdir(os.path.join(subjectspath,subject)) print (' Working On --> ', subject) lh_names = ['rois/destrieux/' + str(label) for label in frontal] lh_names = [label + '_lh_dsx.mif' for label in lh_names] rh_names = ['rois/destrieux/' + str(label) for label in frontal] rh_names = [label + '_rh_dsx.mif' for label in rh_names] lh_name_string = ' '.join(lh_names) rh_name_string = ' '.join(rh_names) maxs = (' -max') max_string = maxs * (len(lh_names) - 1) run.command('mrcalc ' + lh_name_string + ' ' + max_string + ' rois/lh_frontal_lobe.mif -force' ) run.command('mrcalc ' + rh_name_string + ' ' + max_string + ' rois/rh_frontal_lobe.mif -force' ) lh_names = ['rois/destrieux/' + str(label) for label in parietal] lh_names = [label + '_lh_dsx.mif' for label in lh_names] rh_names = ['rois/destrieux/' + str(label) for label in parietal] rh_names = [label + '_rh_dsx.mif' for label in rh_names] lh_name_string = ' '.join(lh_names) rh_name_string = ' '.join(rh_names) maxs = (' -max') max_string = maxs * (len(lh_names) - 1) run.command('mrcalc ' + lh_name_string + ' ' + max_string + ' rois/lh_parietal_lobe.mif -force' ) run.command('mrcalc ' + rh_name_string + ' ' + max_string + ' rois/rh_parietal_lobe.mif -force' ) lh_names = ['rois/destrieux/' + str(label) for label in temporal] lh_names = [label + '_lh_dsx.mif' for label in lh_names]