Пример #1
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')
Пример #2
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')
Пример #3
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))
Пример #4
0
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')
Пример #5
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')
Пример #6
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')
Пример #7
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')
Пример #8
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')
Пример #9
0
def checkFirst(prefix, structures):  #pylint: disable=unused-variable
    import os
    from mrtrix3 import app, file, path  # pylint: disable=redefined-builtin
    vtk_files = [prefix + '-' + struct + '_first.vtk' for struct in structures]
    existing_file_count = sum(
        [os.path.exists(filename) for filename in vtk_files])
    if existing_file_count != len(vtk_files):
        if 'SGE_ROOT' in os.environ:
            app.console(
                'FSL FIRST job has been submitted to SGE; awaiting completion')
            app.console(
                '(note however that FIRST may fail silently, and hence this script may hang indefinitely)'
            )
            file.waitFor(vtk_files)
        else:
            app.error('FSL FIRST has failed; only ' +
                      str(existing_file_count) + ' of ' + str(len(vtk_files)) +
                      ' structures were segmented successfully (check ' +
                      path.toTemp('first.logs', False) + ')')
Пример #10
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 -'
        )
Пример #11
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()
Пример #13
0
def checkFirst(prefix, structures): #pylint: disable=unused-variable
  import os
  from mrtrix3 import app, file, path # pylint: disable=redefined-builtin
  vtk_files = [ prefix + '-' + struct + '_first.vtk' for struct in structures ]
  existing_file_count = sum([ os.path.exists(filename) for filename in vtk_files ])
  if existing_file_count != len(vtk_files):
    if 'SGE_ROOT' in os.environ:
      app.console('FSL FIRST job has been submitted to SGE; awaiting completion')
      app.console('(note however that FIRST may fail silently, and hence this script may hang indefinitely)')
      file.waitFor(vtk_files)
    else:
      app.error('FSL FIRST has failed; only ' + str(existing_file_count) + ' of ' + str(len(vtk_files)) + ' structures were segmented successfully (check ' + path.toTemp('first.logs', False) + ')')
Пример #14
0
def getInputs():
    import os, shutil
    from mrtrix3 import app, path, run
    if app.args.lut:
        run.function(shutil.copyfile, path.fromUser(app.args.lut, False),
                     path.toTemp('LUT.txt', False))
Пример #15
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))
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()])
Пример #17
0
def runSubject(bids_dir, label, output_prefix):

    output_dir = os.path.join(output_prefix, label)
    if os.path.exists(output_dir):
        shutil.rmtree(output_dir)
    os.makedirs(output_dir)
    os.makedirs(os.path.join(output_dir, 'connectome'))
    os.makedirs(os.path.join(output_dir, 'dwi'))

    fsl_path = os.environ.get('FSLDIR', '')
    if not fsl_path:
        app.error(
            'Environment variable FSLDIR is not set; please run appropriate FSL configuration script'
        )

    flirt_cmd = fsl.exeName('flirt')
    fslanat_cmd = fsl.exeName('fsl_anat')
    fsl_suffix = fsl.suffix()

    unring_cmd = 'unring.a64'
    if not find_executable(unring_cmd):
        app.console('Command \'' + unring_cmd +
                    '\' not found; cannot perform Gibbs ringing removal')
        unring_cmd = ''

    dwibiascorrect_algo = '-ants'
    if not find_executable('N4BiasFieldCorrection'):
        # Can't use findFSLBinary() here, since we want to proceed even if it's not found
        if find_executable('fast') or find_executable('fsl5.0-fast'):
            dwibiascorrect_algo = '-fsl'
            app.console('Could not find ANTs program N4BiasFieldCorrection; '
                        'using FSL FAST for bias field correction')
        else:
            dwibiascorrect_algo = ''
            app.warn(
                'Could not find ANTs program \'N4BiasFieldCorrection\' or FSL program \'fast\'; '
                'will proceed without performing DWI bias field correction')

    if not app.args.parcellation:
        app.error(
            'For participant-level analysis, desired parcellation must be provided using the -parcellation option'
        )

    parc_image_path = ''
    parc_lut_file = ''
    mrtrix_lut_file = os.path.join(
        os.path.dirname(os.path.abspath(app.__file__)), os.pardir, os.pardir,
        'share', 'mrtrix3', 'labelconvert')

    if app.args.parcellation == 'fs_2005' or app.args.parcellation == 'fs_2009':
        if not 'FREESURFER_HOME' in os.environ:
            app.error(
                'Environment variable FREESURFER_HOME not set; please verify FreeSurfer installation'
            )
        if not find_executable('recon-all'):
            app.error(
                'Could not find FreeSurfer script recon-all; please verify FreeSurfer installation'
            )
        parc_lut_file = os.path.join(os.environ['FREESURFER_HOME'],
                                     'FreeSurferColorLUT.txt')
        if app.args.parcellation == 'fs_2005':
            mrtrix_lut_file = os.path.join(mrtrix_lut_file, 'fs_default.txt')
        else:
            mrtrix_lut_file = os.path.join(mrtrix_lut_file, 'fs_a2009s.txt')

    if app.args.parcellation == 'aal' or app.args.parcellation == 'aal2':
        mni152_path = os.path.join(fsl_path, 'data', 'standard',
                                   'MNI152_T1_1mm.nii.gz')
        if not os.path.isfile(mni152_path):
            app.error(
                'Could not find MNI152 template image within FSL installation (expected location: '
                + mni152_path + ')')
        if app.args.parcellation == 'aal':
            parc_image_path = os.path.abspath(
                os.path.join(os.sep, 'opt', 'aal', 'ROI_MNI_V4.nii'))
            parc_lut_file = os.path.abspath(
                os.path.join(os.sep, 'opt', 'aal', 'ROI_MNI_V4.txt'))
            mrtrix_lut_file = os.path.join(mrtrix_lut_file, 'aal.txt')
        else:
            parc_image_path = os.path.abspath(
                os.path.join(os.sep, 'opt', 'aal', 'ROI_MNI_V5.nii'))
            parc_lut_file = os.path.abspath(
                os.path.join(os.sep, 'opt', 'aal', 'ROI_MNI_V5.txt'))
            mrtrix_lut_file = os.path.join(mrtrix_lut_file, 'aal2.txt')

    if parc_image_path and not os.path.isfile(parc_image_path):
        if app.args.atlas_path:
            parc_image_path = [
                parc_image_path,
                os.path.join(os.path.dirname(app.args.atlas_path),
                             os.path.basename(parc_image_path))
            ]
            if os.path.isfile(parc_image_path[1]):
                parc_image_path = parc_image_path[1]
            else:
                app.error(
                    'Could not find parcellation image (tested locations: ' +
                    str(parc_image_path) + ')')
        else:
            app.error(
                'Could not find parcellation image (expected location: ' +
                parc_image_path + ')')
    if not os.path.isfile(parc_lut_file):
        if app.args.atlas_path:
            parc_lut_file = [
                parc_lut_file,
                os.path.join(os.path.dirname(app.args.atlas_path),
                             os.path.basename(parc_lut_file))
            ]
            if os.path.isfile(parc_lut_file[1]):
                parc_lut_file = parc_lut_file[1]
            else:
                app.error(
                    'Could not find parcellation lookup table file (tested locations: '
                    + str(parc_lut_file) + ')')
        else:
            app.error(
                'Could not find parcellation lookup table file (expected location: '
                + parc_lut_file + ')')
    if not os.path.exists(mrtrix_lut_file):
        app.error(
            'Could not find MRtrix3 connectome lookup table file (expected location: '
            + mrtrix_lut_file + ')')

    app.makeTempDir()

    # Need to perform an initial import of JSON data using mrconvert; so let's grab the diffusion gradient table as well
    # If no bvec/bval present, need to go down the directory listing
    # Only try to import JSON file if it's actually present
    #   direction in the acquisition they'll need to be split across multiple files
    # May need to concatenate more than one input DWI, since if there's more than one phase-encode direction
    #   in the acquired DWIs (i.e. not just those used for estimating the inhomogeneity field), they will
    #   need to be stored as separate NIfTI files in the 'dwi/' directory.
    dwi_image_list = glob.glob(
        os.path.join(bids_dir, label, 'dwi', label) + '*_dwi.nii*')
    dwi_index = 1
    for entry in dwi_image_list:
        # os.path.split() falls over with .nii.gz extensions; only removes the .gz
        prefix = entry.split(os.extsep)[0]
        if os.path.isfile(prefix + '.bval') and os.path.isfile(prefix +
                                                               '.bvec'):
            prefix = prefix + '.'
        else:
            prefix = os.path.join(bids_dir, 'dwi')
            if not (os.path.isfile(prefix + 'bval')
                    and os.path.isfile(prefix + 'bvec')):
                app.error(
                    'Unable to locate valid diffusion gradient table for image \''
                    + entry + '\'')
        grad_import_option = ' -fslgrad ' + prefix + 'bvec ' + prefix + 'bval'
        json_path = prefix + 'json'
        if os.path.isfile(json_path):
            json_import_option = ' -json_import ' + json_path
        else:
            json_import_option = ''
        run.command('mrconvert ' + entry + grad_import_option +
                    json_import_option + ' ' +
                    path.toTemp('dwi' + str(dwi_index) + '.mif', True))
        dwi_index += 1

    # Go hunting for reversed phase-encode data dedicated to field map estimation
    fmap_image_list = []
    fmap_dir = os.path.join(bids_dir, label, 'fmap')
    fmap_index = 1
    if os.path.isdir(fmap_dir):
        if app.args.preprocessed:
            app.error('fmap/ directory detected for subject \'' + label +
                      '\' despite use of ' + option_prefix +
                      'preprocessed option')
        fmap_image_list = glob.glob(
            os.path.join(fmap_dir, label) + '_dir-*_epi.nii*')
        for entry in fmap_image_list:
            prefix = entry.split(os.extsep)[0]
            json_path = prefix + '.json'
            with open(json_path, 'r') as f:
                json_elements = json.load(f)
            if 'IntendedFor' in json_elements and not any(
                    i.endswith(json_elements['IntendedFor'])
                    for i in dwi_image_list):
                app.console('Image \'' + entry +
                            '\' is not intended for use with DWIs; skipping')
                continue
            if os.path.isfile(json_path):
                json_import_option = ' -json_import ' + json_path
                # fmap files will not come with any gradient encoding in the JSON;
                #   therefore we need to add it manually ourselves so that mrcat / mrconvert can
                #   appropriately handle the table once these images are concatenated with the DWIs
                fmap_image_size = image.Header(entry).size()
                fmap_image_num_volumes = 1 if len(
                    fmap_image_size) == 3 else fmap_image_size[3]
                run.command('mrconvert ' + entry + json_import_option +
                            ' -set_property dw_scheme \"' +
                            '\\n'.join(['0,0,1,0'] * fmap_image_num_volumes) +
                            '\" ' +
                            path.toTemp('fmap' + str(fmap_index) +
                                        '.mif', True))
                fmap_index += 1
            else:
                app.warn('No corresponding .json file found for image \'' +
                         entry + '\'; skipping')

        fmap_image_list = [
            'fmap' + str(index) + '.mif' for index in range(1, fmap_index)
        ]
    # If there's no data in fmap/ directory, need to check to see if there's any phase-encoding
    #   contrast within the input DWI(s)
    elif len(dwi_image_list) < 2 and not app.args.preprocessed:
        app.error(
            'Inadequate data for pre-processing of subject \'' + label +
            '\': No phase-encoding contrast in input DWIs or fmap/ directory')

    dwi_image_list = [
        'dwi' + str(index) + '.mif' for index in range(1, dwi_index)
    ]

    # Import anatomical image
    run.command('mrconvert ' +
                os.path.join(bids_dir, label, 'anat', label + '_T1w.nii.gz') +
                ' ' + path.toTemp('T1.mif', True))

    cwd = os.getcwd()
    app.gotoTempDir()

    dwipreproc_se_epi = ''
    dwipreproc_se_epi_option = ''

    # For automated testing, down-sampled images are used. However, this invalidates the requirements of
    #   both MP-PCA denoising and Gibbs ringing removal. In addition, eddy can still take a long time
    #   despite the down-sampling. Therefore, provide images that have been pre-processed to the stage
    #   where it is still only DWI, JSON & bvecs/bvals that need to be provided.
    if app.args.preprocessed:

        if len(dwi_image_list) > 1:
            app.error(
                'If DWIs have been pre-processed, then only a single DWI file should need to be provided'
            )
        app.console(
            'Skipping MP-PCA denoising, ' +
            ('Gibbs ringing removal, ' if unring_cmd else '') +
            'distortion correction and bias field correction due to use of ' +
            option_prefix + 'preprocessed option')
        run.function(os.rename, dwi_image_list[0], 'dwi.mif')

    else:  # Do initial image pre-processing (denoising, Gibbs ringing removal if available, distortion correction & bias field correction) as normal

        # Concatenate any SE EPI images with the DWIs before denoising (& unringing), then
        #   separate them again after the fact
        dwidenoise_input = 'dwidenoise_input.mif'
        fmap_num_volumes = 0
        if fmap_image_list:
            run.command('mrcat ' + ' '.join(fmap_image_list) +
                        ' fmap_cat.mif -axis 3')
            for i in fmap_image_list:
                file.delTemporary(i)
            fmap_num_volumes = image.Header('fmap_cat.mif').size()[3]
            dwidenoise_input = 'all_cat.mif'
            run.command('mrcat fmap_cat.mif ' + ' '.join(dwi_image_list) +
                        ' ' + dwidenoise_input + ' -axis 3')
            file.delTemporary('fmap_cat.mif')
        else:
            # Even if no explicit fmap images, may still need to concatenate multiple DWI inputs
            if len(dwi_image_list) > 1:
                run.command('mrcat ' + ' '.join(dwi_image_list) + ' ' +
                            dwidenoise_input + ' -axis 3')
            else:
                run.function(shutil.move, dwi_image_list[0], dwidenoise_input)

        for i in dwi_image_list:
            file.delTemporary(i)

        # Step 1: Denoise
        run.command('dwidenoise ' + dwidenoise_input + ' dwi_denoised.' +
                    ('nii' if unring_cmd else 'mif'))
        if unring_cmd:
            run.command('mrinfo ' + dwidenoise_input +
                        ' -json_keyval input.json')
        file.delTemporary(dwidenoise_input)

        # Step 2: Gibbs ringing removal (if available)
        if unring_cmd:
            run.command(unring_cmd + ' dwi_denoised.nii dwi_unring' +
                        fsl_suffix + ' -n 100')
            file.delTemporary('dwi_denoised.nii')
            unring_output_path = fsl.findImage('dwi_unring')
            run.command('mrconvert ' + unring_output_path +
                        ' dwi_unring.mif -json_import input.json')
            file.delTemporary(unring_output_path)
            file.delTemporary('input.json')

        # If fmap images and DWIs have been concatenated, now is the time to split them back apart
        dwipreproc_input = 'dwi_unring.mif' if unring_cmd else 'dwi_denoised.mif'

        if fmap_num_volumes:
            cat_input = 'dwi_unring.mif' if unring_cmd else 'dwi_denoised.mif'
            dwipreproc_se_epi = 'se_epi.mif'
            run.command('mrconvert ' + cat_input + ' ' + dwipreproc_se_epi +
                        ' -coord 3 0:' + str(fmap_num_volumes - 1))
            cat_num_volumes = image.Header(cat_input).size()[3]
            run.command('mrconvert ' + cat_input +
                        ' dwipreproc_in.mif -coord 3 ' +
                        str(fmap_num_volumes) + ':' + str(cat_num_volumes - 1))
            file.delTemporary(dwipreproc_input)
            dwipreproc_input = 'dwipreproc_in.mif'
            dwipreproc_se_epi_option = ' -se_epi ' + dwipreproc_se_epi

        # Step 3: Distortion correction
        run.command('dwipreproc ' + dwipreproc_input +
                    ' dwi_preprocessed.mif -rpe_header' +
                    dwipreproc_se_epi_option)
        file.delTemporary(dwipreproc_input)
        if dwipreproc_se_epi:
            file.delTemporary(dwipreproc_se_epi)

        # Step 4: Bias field correction
        if dwibiascorrect_algo:
            run.command('dwibiascorrect dwi_preprocessed.mif dwi.mif ' +
                        dwibiascorrect_algo)
            file.delTemporary('dwi_preprocessed.mif')
        else:
            run.function(shutil.move, 'dwi_preprocessed.mif', 'dwi.mif')

    # No longer branching based on whether or not -preprocessed was specified

    # Step 5: Generate a brain mask for DWI
    run.command('dwi2mask dwi.mif dwi_mask.mif')

    # Step 6: Perform brain extraction on the T1 image in its original space
    #         (this is necessary for histogram matching prior to registration)
    #         Use fsl_anat script
    run.command('mrconvert T1.mif T1.nii -stride -1,+2,+3')
    run.command(fslanat_cmd + ' -i T1.nii --noseg --nosubcortseg')
    run.command('mrconvert ' +
                fsl.findImage('T1.anat' + os.sep + 'T1_biascorr_brain_mask') +
                ' T1_mask.mif -datatype bit')
    run.command('mrconvert ' +
                fsl.findImage('T1.anat' + os.sep + 'T1_biascorr_brain') +
                ' T1_biascorr_brain.mif')
    file.delTemporary('T1.anat')

    # Step 7: Generate target images for T1->DWI registration
    run.command('dwiextract dwi.mif -bzero - | '
                'mrcalc - 0.0 -max - | '
                'mrmath - mean -axis 3 dwi_meanbzero.mif')
    run.command(
        'mrcalc 1 dwi_meanbzero.mif -div dwi_mask.mif -mult - | '
        'mrhistmatch - T1_biascorr_brain.mif dwi_pseudoT1.mif -mask_input dwi_mask.mif -mask_target T1_mask.mif'
    )
    run.command(
        'mrcalc 1 T1_biascorr_brain.mif -div T1_mask.mif -mult - | '
        'mrhistmatch - dwi_meanbzero.mif T1_pseudobzero.mif -mask_input T1_mask.mif -mask_target dwi_mask.mif'
    )

    # Step 8: Perform T1->DWI registration
    #         Note that two registrations are performed: Even though we have a symmetric registration,
    #         generation of the two histogram-matched images means that you will get slightly different
    #         answers depending on which synthesized image & original image you use.
    run.command(
        'mrregister T1_biascorr_brain.mif dwi_pseudoT1.mif -type rigid -mask1 T1_mask.mif -mask2 dwi_mask.mif -rigid rigid_T1_to_pseudoT1.txt'
    )
    file.delTemporary('T1_biascorr_brain.mif')
    run.command(
        'mrregister T1_pseudobzero.mif dwi_meanbzero.mif -type rigid -mask1 T1_mask.mif -mask2 dwi_mask.mif -rigid rigid_pseudobzero_to_bzero.txt'
    )
    file.delTemporary('dwi_meanbzero.mif')
    run.command(
        'transformcalc rigid_T1_to_pseudoT1.txt rigid_pseudobzero_to_bzero.txt average rigid_T1_to_dwi.txt'
    )
    file.delTemporary('rigid_T1_to_pseudoT1.txt')
    file.delTemporary('rigid_pseudobzero_to_bzero.txt')
    run.command(
        'mrtransform T1.mif T1_registered.mif -linear rigid_T1_to_dwi.txt')
    file.delTemporary('T1.mif')
    # Note: Since we're using a mask from fsl_anat (which crops the FoV), but using it as input to 5ttge fsl
    #   (which is receiving the raw T1), we need to resample in order to have the same dimensions between these two
    run.command(
        'mrtransform T1_mask.mif T1_mask_registered.mif -linear rigid_T1_to_dwi.txt -template T1_registered.mif -interp nearest'
    )
    file.delTemporary('T1_mask.mif')

    # Step 9: Generate 5TT image for ACT
    run.command(
        '5ttgen fsl T1_registered.mif 5TT.mif -mask T1_mask_registered.mif')
    file.delTemporary('T1_mask_registered.mif')

    # Step 10: Estimate response functions for spherical deconvolution
    run.command(
        'dwi2response dhollander dwi.mif response_wm.txt response_gm.txt response_csf.txt -mask dwi_mask.mif'
    )

    # Step 11: Determine whether we are working with single-shell or multi-shell data
    shells = [
        int(round(float(value)))
        for value in image.mrinfo('dwi.mif', 'shellvalues').strip().split()
    ]
    multishell = (len(shells) > 2)

    # Step 12: Perform spherical deconvolution
    #          Use a dilated mask for spherical deconvolution as a 'safety margin' -
    #          ACT should be responsible for stopping streamlines before they reach the edge of the DWI mask
    run.command('maskfilter dwi_mask.mif dilate dwi_mask_dilated.mif -npass 3')
    if multishell:
        run.command(
            'dwi2fod msmt_csd dwi.mif response_wm.txt FOD_WM.mif response_gm.txt FOD_GM.mif response_csf.txt FOD_CSF.mif '
            '-mask dwi_mask_dilated.mif -lmax 10,0,0')
        file.delTemporary('FOD_GM.mif')
        file.delTemporary('FOD_CSF.mif')
    else:
        # Still use the msmt_csd algorithm with single-shell data: Use hard non-negativity constraint
        # Also incorporate the CSF response to provide some fluid attenuation
        run.command(
            'dwi2fod msmt_csd dwi.mif response_wm.txt FOD_WM.mif response_csf.txt FOD_CSF.mif '
            '-mask dwi_mask_dilated.mif -lmax 10,0')
        file.delTemporary('FOD_CSF.mif')

    # Step 13: Generate the grey matter parcellation
    #          The necessary steps here will vary significantly depending on the parcellation scheme selected
    run.command(
        'mrconvert T1_registered.mif T1_registered.nii -stride +1,+2,+3')
    if app.args.parcellation == 'fs_2005' or app.args.parcellation == 'fs_2009':

        # Run FreeSurfer pipeline on this subject's T1 image
        run.command('recon-all -sd ' + app.tempDir +
                    ' -subjid freesurfer -i T1_registered.nii')
        run.command('recon-all -sd ' + app.tempDir +
                    ' -subjid freesurfer -all')

        # Grab the relevant parcellation image and target lookup table for conversion
        parc_image_path = os.path.join('freesurfer', 'mri')
        if app.args.parcellation == 'fs_2005':
            parc_image_path = os.path.join(parc_image_path, 'aparc+aseg.mgz')
        else:
            parc_image_path = os.path.join(parc_image_path,
                                           'aparc.a2009s+aseg.mgz')

        # Perform the index conversion
        run.command('labelconvert ' + parc_image_path + ' ' + parc_lut_file +
                    ' ' + mrtrix_lut_file + ' parc_init.mif')
        if app.cleanup:
            run.function(shutil.rmtree, 'freesurfer')

        # Fix the sub-cortical grey matter parcellations using FSL FIRST
        run.command('labelsgmfix parc_init.mif T1_registered.mif ' +
                    mrtrix_lut_file + ' parc.mif')
        file.delTemporary('parc_init.mif')

    elif app.args.parcellation == 'aal' or app.args.parcellation == 'aal2':

        # Can use MNI152 image provided with FSL for registration
        run.command(flirt_cmd + ' -ref ' + mni152_path +
                    ' -in T1_registered.nii -omat T1_to_MNI_FLIRT.mat -dof 12')
        run.command('transformconvert T1_to_MNI_FLIRT.mat T1_registered.nii ' +
                    mni152_path + ' flirt_import T1_to_MNI_MRtrix.mat')
        file.delTemporary('T1_to_MNI_FLIRT.mat')
        run.command(
            'transformcalc T1_to_MNI_MRtrix.mat invert MNI_to_T1_MRtrix.mat')
        file.delTemporary('T1_to_MNI_MRtrix.mat')
        run.command('mrtransform ' + parc_image_path +
                    ' AAL.mif -linear MNI_to_T1_MRtrix.mat '
                    '-template T1_registered.mif -interp nearest')
        file.delTemporary('MNI_to_T1_MRtrix.mat')
        run.command('labelconvert AAL.mif ' + parc_lut_file + ' ' +
                    mrtrix_lut_file + ' parc.mif')
        file.delTemporary('AAL.mif')

    else:
        app.error('Unknown parcellation scheme requested: ' +
                  app.args.parcellation)
    file.delTemporary('T1_registered.nii')

    # Step 14: Generate the tractogram
    # If not manually specified, determine the appropriate number of streamlines based on the number of nodes in the parcellation:
    #   mean edge weight of 1,000 streamlines
    # A smaller FOD amplitude threshold of 0.06 (default 0.1) is used for tracking due to the use of the msmt_csd
    #   algorithm, which imposes a hard rather than soft non-negativity constraint
    num_nodes = int(image.statistic('parc.mif', 'max'))
    num_streamlines = 1000 * num_nodes * num_nodes
    if app.args.streamlines:
        num_streamlines = app.args.streamlines
    run.command(
        'tckgen FOD_WM.mif tractogram.tck -act 5TT.mif -backtrack -crop_at_gmwmi -cutoff 0.06 -maxlength 250 -power 0.33 '
        '-select ' + str(num_streamlines) + ' -seed_dynamic FOD_WM.mif')

    # Step 15: Use SIFT2 to determine streamline weights
    fd_scale_gm_option = ''
    if not multishell:
        fd_scale_gm_option = ' -fd_scale_gm'
    run.command(
        'tcksift2 tractogram.tck FOD_WM.mif weights.csv -act 5TT.mif -out_mu mu.txt'
        + fd_scale_gm_option)

    # Step 16: Generate a TDI (to verify that SIFT2 has worked correctly)
    with open('mu.txt', 'r') as f:
        mu = float(f.read())
    run.command(
        'tckmap tractogram.tck -tck_weights_in weights.csv -template FOD_WM.mif -precise - | '
        'mrcalc - ' + str(mu) + ' -mult tdi.mif')

    # Step 17: Generate the connectome
    #          Only provide the standard density-weighted connectome for now
    run.command(
        'tck2connectome tractogram.tck parc.mif connectome.csv -tck_weights_in weights.csv'
    )
    file.delTemporary('weights.csv')

    # Move necessary files to output directory
    run.function(
        shutil.copy, 'connectome.csv',
        os.path.join(output_dir, 'connectome', label + '_connectome.csv'))
    run.command('mrconvert dwi.mif ' +
                os.path.join(output_dir, 'dwi', label + '_dwi.nii.gz') +
                ' -export_grad_fsl ' +
                os.path.join(output_dir, 'dwi', label + '_dwi.bvec') + ' ' +
                os.path.join(output_dir, 'dwi', label + '_dwi.bval') +
                ' -json_export ' +
                os.path.join(output_dir, 'dwi', label + '_dwi.json'))
    run.command('mrconvert tdi.mif ' +
                os.path.join(output_dir, 'dwi', label + '_tdi.nii.gz'))
    run.function(shutil.copy, 'mu.txt',
                 os.path.join(output_dir, 'connectome', label + '_mu.txt'))
    run.function(shutil.copy, 'response_wm.txt',
                 os.path.join(output_dir, 'dwi', label + '_response.txt'))

    # Manually wipe and zero the temp directory (since we might be processing more than one subject)
    os.chdir(cwd)
    if app.cleanup:
        app.console('Deleting temporary directory ' + app.tempDir)
        # Can't use run.function() here; it'll try to write to the log file that resides in the temp directory just deleted
        shutil.rmtree(app.tempDir)
    else:
        app.console('Contents of temporary directory kept, location: ' +
                    app.tempDir)
    app.tempDir = ''
Пример #18
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')
Пример #19
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:
        call('mrconvert -force -stride -1,2,3,4 -fslgrad ' + bveclist[0] +
             ' ' + bvallist[0] + ' ' + ''.join(DWInlist) + ''.join(DWIext) +
             ' ' + path.toTemp('dwi.mif', True),
             shell=True)
    else:
        call('mrconvert -force -stride -1,2,3,4 ' + ''.join(DWInlist) + ' ' +
             path.toTemp('dwi.mif', True),
             shell=True)
else:
    for (idx, i) in enumerate(DWInlist):
        if not isdicom:
            call('mrconvert -force -stride -1,2,3,4 -fslgrad ' +
                 bveclist[idx] + ' ' + bvallist[idx] + ' ' + i + DWIext[idx] +
                 ' ' + path.toTemp('dwi' + str(idx) + '.mif', True),
                 shell=True)
        else:
            call('mrconvert -force -stride -1,2,3,4 ' + i + ' ' +
                 path.toTemp('dwi' + str(idx) + '.mif', True),
Пример #20
0
def getInputs(): #pylint: disable=unused-variable
  import os, shutil #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))
Пример #21
0
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()