diff --git a/nipype/interfaces/fsl/preprocess.py b/nipype/interfaces/fsl/preprocess.py index 842bbbe978..eaab2a830e 100644 --- a/nipype/interfaces/fsl/preprocess.py +++ b/nipype/interfaces/fsl/preprocess.py @@ -25,7 +25,7 @@ from ..base import (TraitedSpec, File, InputMultiPath, OutputMultiPath, Undefined, traits, isdefined) -from .base import FSLCommand, FSLCommandInputSpec +from .base import FSLCommand, FSLCommandInputSpec, Info class BETInputSpec(FSLCommandInputSpec): @@ -750,10 +750,12 @@ class FNIRTInputSpec(FSLCommandInputSpec): desc='name of file containing affine transform') inwarp_file = File(exists=True, argstr='--inwarp=%s', desc='name of file containing initial non-linear warps') - in_intensitymap_file = File(exists=True, argstr='--intin=%s', - desc=('name of file/files containing initial ' - 'intensity maping usually generated by ' - 'previous fnirt run')) + in_intensitymap_file = traits.List(File(exists=True), argstr='--intin=%s', + copyfiles=False, minlen=1, maxlen=2, + desc=('name of file/files containing ' + 'initial intensity mapping ' + 'usually generated by previous ' + 'fnirt run')) fieldcoeff_file = traits.Either( traits.Bool, File, argstr='--cout=%s', desc='name of output file with field coefficients or true') @@ -907,8 +909,9 @@ class FNIRTOutputSpec(TraitedSpec): field_file = File(desc='file with warp field') jacobian_file = File(desc='file containing Jacobian of the field') modulatedref_file = File(desc='file containing intensity modulated --ref') - out_intensitymap_file = File( - desc='file containing info pertaining to intensity mapping') + out_intensitymap_file = traits.List( + File, minlen=2, maxlen=2, + desc='files containing info pertaining to intensity mapping') log_file = File(desc='Name of log-file') @@ -975,9 +978,23 @@ def _list_outputs(self): change_ext=change_ext) else: outputs[key] = os.path.abspath(inval) + + if key == 'out_intensitymap_file' and isdefined(outputs[key]): + basename = FNIRT.intensitymap_file_basename(outputs[key]) + outputs[key] = [ + outputs[key], + '%s.txt' % basename, + ] return outputs def _format_arg(self, name, spec, value): + if name in ('in_intensitymap_file', 'out_intensitymap_file'): + if name == 'out_intensitymap_file': + value = self._list_outputs()[name] + value = [FNIRT.intensitymap_file_basename(v) for v in value] + assert len(set(value)) == 1, ( + 'Found different basenames for {}: {}'.format(name, value)) + return spec.argstr % value[0] if name in list(self.filemap.keys()): return spec.argstr % self._list_outputs()[name] return super(FNIRT, self)._format_arg(name, spec, value) @@ -1005,6 +1022,17 @@ def write_config(self, configfile): fid.write('%s\n' % (item)) fid.close() + @classmethod + def intensitymap_file_basename(cls, f): + """Removes valid intensitymap extensions from `f`, returning a basename + that can refer to both intensitymap files. + """ + for ext in list(Info.ftypes.values()) + ['.txt']: + if f.endswith(ext): + return f[:-len(ext)] + # TODO consider warning for this case + return f + class ApplyWarpInputSpec(FSLCommandInputSpec): in_file = File(exists=True, argstr='--in=%s', diff --git a/nipype/interfaces/fsl/tests/test_preprocess.py b/nipype/interfaces/fsl/tests/test_preprocess.py index bcf52fb5f3..f9242c4b26 100644 --- a/nipype/interfaces/fsl/tests/test_preprocess.py +++ b/nipype/interfaces/fsl/tests/test_preprocess.py @@ -353,6 +353,7 @@ def test_mcflirt(setup_flirt): def test_fnirt(setup_flirt): tmpdir, infile, reffile = setup_flirt + os.chdir(tmpdir) fnirt = fsl.FNIRT() assert fnirt.cmd == 'fnirt' @@ -404,64 +405,81 @@ def test_fnirt(setup_flirt): fnirt.run() fnirt.inputs.in_file = infile fnirt.inputs.ref_file = reffile + intmap_basename = '%s_intmap' % fsl.FNIRT.intensitymap_file_basename(infile) + intmap_image = fsl_name(fnirt, intmap_basename) + intmap_txt = '%s.txt' % intmap_basename + # doing this to create the file to pass tests for file existence + with open(intmap_image, 'w'): + pass + with open(intmap_txt, 'w'): + pass # test files - opt_map = { - 'affine_file': ('--aff='), - 'inwarp_file': ('--inwarp='), - 'in_intensitymap_file': ('--intin='), - 'config_file': ('--config='), - 'refmask_file': ('--refmask='), - 'inmask_file': ('--inmask='), - 'field_file': ('--fout='), - 'jacobian_file': ('--jout='), - 'modulatedref_file': ('--refout='), - 'out_intensitymap_file': ('--intout='), - 'log_file': ('--logout=')} - - for name, settings in list(opt_map.items()): + opt_map = [ + ('affine_file', '--aff=%s' % infile, infile), + ('inwarp_file', '--inwarp=%s' % infile, infile), + ('in_intensitymap_file', '--intin=%s' % intmap_basename, [intmap_image]), + ('in_intensitymap_file', + '--intin=%s' % intmap_basename, + [intmap_image, intmap_txt]), + ('config_file', '--config=%s' % infile, infile), + ('refmask_file', '--refmask=%s' % infile, infile), + ('inmask_file', '--inmask=%s' % infile, infile), + ('field_file', '--fout=%s' % infile, infile), + ('jacobian_file', '--jout=%s' % infile, infile), + ('modulatedref_file', '--refout=%s' % infile, infile), + ('out_intensitymap_file', + '--intout=%s' % intmap_basename, True), + ('out_intensitymap_file', '--intout=%s' % intmap_basename, intmap_image), + ('fieldcoeff_file', '--cout=%s' % infile, infile), + ('log_file', '--logout=%s' % infile, infile)] + + for (name, settings, arg) in opt_map: fnirt = fsl.FNIRT(in_file=infile, ref_file=reffile, - **{name: infile}) + **{name: arg}) - if name in ('config_file', 'affine_file', 'field_file'): - cmd = 'fnirt %s%s --in=%s '\ + if name in ('config_file', 'affine_file', 'field_file', 'fieldcoeff_file'): + cmd = 'fnirt %s --in=%s '\ '--logout=%s '\ - '--ref=%s --iout=%s' % (settings, infile, infile, log, + '--ref=%s --iout=%s' % (settings, infile, log, reffile, iout) elif name in ('refmask_file'): cmd = 'fnirt --in=%s '\ '--logout=%s --ref=%s '\ - '%s%s '\ + '%s '\ '--iout=%s' % (infile, log, reffile, - settings, infile, + settings, iout) elif name in ('in_intensitymap_file', 'inwarp_file', 'inmask_file', 'jacobian_file'): cmd = 'fnirt --in=%s '\ - '%s%s '\ + '%s '\ '--logout=%s --ref=%s '\ '--iout=%s' % (infile, - settings, infile, + settings, log, reffile, iout) elif name in ('log_file'): cmd = 'fnirt --in=%s '\ - '%s%s --ref=%s '\ + '%s --ref=%s '\ '--iout=%s' % (infile, - settings, infile, + settings, reffile, iout) else: cmd = 'fnirt --in=%s '\ - '--logout=%s %s%s '\ + '--logout=%s %s '\ '--ref=%s --iout=%s' % (infile, log, - settings, infile, + settings, reffile, iout) assert fnirt.cmdline == cmd + if name == 'out_intensitymap_file': + assert fnirt._list_outputs()['out_intensitymap_file'] == [ + intmap_image, intmap_txt] @pytest.mark.skipif(no_fsl(), reason="fsl is not installed") def test_applywarp(setup_flirt):