Esempio n. 1
0
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)
Esempio n. 2
0
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')
Esempio n. 3
0
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')
Esempio n. 4
0
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')
Esempio n. 5
0
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)
Esempio n. 6
0
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')
Esempio n. 7
0
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))
Esempio n. 8
0
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')
Esempio n. 9
0
File: fsl.py Progetto: okjoh/mrtrix3
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')
Esempio n. 10
0
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')
Esempio n. 11
0
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')
Esempio n. 12
0
 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')
Esempio n. 13
0
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)
Esempio n. 14
0
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')
Esempio n. 15
0
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')
Esempio n. 16
0
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')
Esempio n. 17
0
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')
Esempio n. 18
0
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')
Esempio n. 19
0
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)
Esempio n. 20
0
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')
Esempio n. 21
0
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)
Esempio n. 22
0
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))
Esempio n. 23
0
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)
Esempio n. 24
0
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')
Esempio n. 25
0
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)
Esempio n. 26
0
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))
Esempio n. 27
0
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))
Esempio n. 29
0
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))
Esempio n. 30
0
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 -')
Esempio n. 31
0
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('-------')
Esempio n. 32
0
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')
Esempio n. 33
0
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))
Esempio n. 34
0
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))
Esempio n. 35
0
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'
    )
Esempio n. 36
0
        # 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')
Esempio n. 37
0
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))
Esempio n. 38
0
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'))
Esempio n. 39
0
 def command(self, cmd):
     from mrtrix3 import run  #pylint: disable=import-outside-toplevel
     assert self.valid
     run.command(cmd)
     self._increment()
Esempio n. 40
0
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()
Esempio n. 42
0
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 -'
        )
Esempio n. 43
0
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))
Esempio n. 44
0
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
Esempio n. 45
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]