From d1cee472d0b6659112acdb136814fc69f580f6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81my=20Guillon?= Date: Thu, 23 Mar 2017 18:54:30 +0100 Subject: [PATCH 1/5] Add SPM Fieldmap Tool wrapper Added: - VDM Calculation pre-substracted phase case (SIEMENS machines) Todo: - Support VDM Application - Support different magnitude and phase file types --- nipype/interfaces/spm/__init__.py | 2 +- nipype/interfaces/spm/preprocess.py | 141 ++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 1 deletion(-) diff --git a/nipype/interfaces/spm/__init__.py b/nipype/interfaces/spm/__init__.py index de829463fb..c4120db124 100644 --- a/nipype/interfaces/spm/__init__.py +++ b/nipype/interfaces/spm/__init__.py @@ -5,7 +5,7 @@ from .base import (Info, SPMCommand, logger, no_spm, scans_for_fname, scans_for_fnames) -from .preprocess import (SliceTiming, Realign, Coregister, Normalize, +from .preprocess import (FieldMap, SliceTiming, Realign, Coregister, Normalize, Normalize12, Segment, Smooth, NewSegment, DARTEL, DARTELNorm2MNI, CreateWarped, VBMSegment) from .model import (Level1Design, EstimateModel, EstimateContrast, Threshold, diff --git a/nipype/interfaces/spm/preprocess.py b/nipype/interfaces/spm/preprocess.py index 9039c03aad..6acfff7da4 100644 --- a/nipype/interfaces/spm/preprocess.py +++ b/nipype/interfaces/spm/preprocess.py @@ -30,6 +30,147 @@ __docformat__ = 'restructuredtext' +class FieldMapInputSpec(SPMCommandInputSpec): + jobtype = traits.Enum('calculatevdm', 'applyvdm', usedefault=True, + desc='one of: calculatevdm, applyvdm') + phase = File(mandatory=True, exists=True, copyfile=False, + field='subj.data.presubphasemag.phase', + desc='presubstracted phase file') + magnitude = File(mandatory=True, exists=True, copyfile=False, + field='subj.data.presubphasemag.magnitude', + desc='presubstracted magnitude file') + et = traits.List(traits.Float(), minlen=2, maxlen=2, mandatory=True, + field='subj.defaults.defaultsval.et', + desc='short and long echo times') + maskbrain = traits.Bool(True, usedefault=True, + field='subj.defaults.defaultsval.maskbrain', + desc='masking or no masking of the brain') + blipdir = traits.Enum(1, -1, mandatory=True, + field='subj.defaults.defaultsval.blipdir', + desc='polarity of the phase-encode blips') + tert = traits.Float(mandatory=True, + field='subj.defaults.defaultsval.tert', + desc='total EPI readout time') + epifm = traits.Bool(False, usedefault=True, + field='subj.defaults.defaultsval.epifm', + desc='epi-based field map'); + ajm = traits.Bool(False, usedefault=True, + field='subj.defaults.defaultsval.ajm', + desc='jacobian modulation'); + # Unwarping defaults parameters + method = traits.Enum('Mark3D', 'Mark2D', 'Huttonish', usedefault=True, + desc='One of: Mark3D, Mark2D, Huttonish', + field='subj.defaults.defaultsval.uflags.method'); + fwhm = traits.Range(low=0, value=10, usedefault=True, + field='subj.defaults.defaultsval.uflags.fwhm', + desc='gaussian smoothing kernel width'); + pad = traits.Range(low=0, value=0, usedefault=True, + field='subj.defaults.defaultsval.uflags.pad', + desc='padding kernel width'); + ws = traits.Bool(True, usedefault=True, + field='subj.defaults.defaultsval.uflags.ws', + desc='weighted smoothing'); + # Brain mask defaults parameters + template = traits.File(copyfile=False, exists=True, + field='subj.defaults.defaultsval.mflags.template', + desc='template image for brain masking'); + fwhm = traits.Range(low=0, value=5, usedefault=True, + field='subj.defaults.defaultsval.mflags.fwhm', + desc='gaussian smoothing kernel width'); + nerode = traits.Range(low=0, value=2, usedefault=True, + field='subj.defaults.defaultsval.mflags.nerode', + desc='number of erosions'); + ndilate = traits.Range(low=0, value=4, usedefault=True, + field='subj.defaults.defaultsval.mflags.ndilate', + desc='number of erosions'); + thresh = traits.Float(0.5, usedefault=True, + field='subj.defaults.defaultsval.mflags.thresh', + desc='threshold used to create brain mask from segmented data'); + reg = traits.Float(0.02, usedefault=True, + field='subj.defaults.defaultsval.mflags.reg', + desc='regularization value used in the segmentation'); + # EPI unwarping for quality check + epi = traits.File(copyfile=False, exists=True, mandatory=True, + field='subj.session.epi', + desc='EPI to unwarp'); + matchvdm = traits.Bool(True, usedefault=True, + field='subj.matchvdm', + desc='match VDM to EPI'); + sessname = traits.String('_run-', usedefault=True, + field='subj.sessname', + desc='VDM filename extension'); + writeunwarped = traits.Bool(False, usedefault=True, + field='subj.writeunwarped', + desc='write unwarped EPI'); + anat = traits.File(copyfile=False, exists=True, + field='subj.anat', + desc='anatomical image for comparison'); + matchanat = traits.Bool(True, usedefault=True, + field='subj.matchanat', + desc='match anatomical image to EPI'); + + +class FieldMapOutputSpec(TraitedSpec): + vdm = File(exists=True, desc='voxel difference map') + + +class FieldMap(SPMCommand): + """Use spm to calculate fieldmap vdm. + + http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=19 + + To do + ----- + Deal with real/imag magnitude images and with the two phase files case. + + Examples + -------- + >>> from nipype.interfaces.spm import FieldMap + >>> fm = FieldMap() + >>> fm.inputs.phase = 'phasediff.nii' + >>> fm.inputs.magnitude = 'magnitude1.nii' + >>> fm.inputs.et = [5.19, 7.65] + >>> fm.inputs.blipdir = 1 + >>> fm.inputs.tert = 15.6 + >>> fm.inputs.epi = 'bold.nii' + >>> fm.run() # doctest: +SKIP + + """ + + input_spec = FieldMapInputSpec + output_spec = FieldMapOutputSpec + _jobtype = 'tools' + _jobname = 'fieldmap' + + def _format_arg(self, opt, spec, val): + """Convert input to appropriate format for spm + """ + if opt == 'phase' or opt == 'magnitude' or opt == 'anat': + return scans_for_fname(filename_to_list(val)) + if opt == 'epi' or opt == 'magnitude': + return scans_for_fname(filename_to_list(val)) + + return super(FieldMap, self)._format_arg(opt, spec, val) + + def _parse_inputs(self): + """validate spm fieldmap options if set to None ignore + """ + einputs = super(FieldMap, self)._parse_inputs() + jobtype = self.inputs.jobtype + return [{'%s' % (jobtype): einputs[0]}] + + def _list_outputs(self): + outputs = self._outputs().get() + jobtype = self.inputs.jobtype + if jobtype == "calculatevdm": + outputs['vdm'] = [] + for phase in filename_to_list(self.inputs.phase): + outputs['vdm'].append(fname_presuffix(phase, prefix='vdm5_sc')) + outputs['vdm'] = list_to_filename(outputs['vdm']) + + return outputs + + class SliceTimingInputSpec(SPMCommandInputSpec): in_files = InputMultiPath(traits.Either(traits.List(File(exists=True)), File(exists=True)), field='scans', From 0fd77fc23893afc9f4ecccbc2cc807a6003a6d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81my=20Guillon?= Date: Wed, 7 Feb 2018 15:48:21 +0100 Subject: [PATCH 2/5] Add first remarks from PR --- nipype/interfaces/spm/preprocess.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/nipype/interfaces/spm/preprocess.py b/nipype/interfaces/spm/preprocess.py index 6acfff7da4..1f35acc634 100644 --- a/nipype/interfaces/spm/preprocess.py +++ b/nipype/interfaces/spm/preprocess.py @@ -23,7 +23,7 @@ from ...utils.filemanip import (fname_presuffix, filename_to_list, list_to_filename, split_filename) from ..base import (OutputMultiPath, TraitedSpec, isdefined, - traits, InputMultiPath, File) + traits, InputMultiPath, File, Str) from .base import (SPMCommand, scans_for_fname, func_is_3d, scans_for_fnames, SPMCommandInputSpec) @@ -39,7 +39,7 @@ class FieldMapInputSpec(SPMCommandInputSpec): magnitude = File(mandatory=True, exists=True, copyfile=False, field='subj.data.presubphasemag.magnitude', desc='presubstracted magnitude file') - et = traits.List(traits.Float(), minlen=2, maxlen=2, mandatory=True, + et = traits.Tuple(traits.Float, traits.Float, mandatory=True, field='subj.defaults.defaultsval.et', desc='short and long echo times') maskbrain = traits.Bool(True, usedefault=True, @@ -71,7 +71,7 @@ class FieldMapInputSpec(SPMCommandInputSpec): field='subj.defaults.defaultsval.uflags.ws', desc='weighted smoothing'); # Brain mask defaults parameters - template = traits.File(copyfile=False, exists=True, + template = File(copyfile=False, exists=True, field='subj.defaults.defaultsval.mflags.template', desc='template image for brain masking'); fwhm = traits.Range(low=0, value=5, usedefault=True, @@ -90,19 +90,19 @@ class FieldMapInputSpec(SPMCommandInputSpec): field='subj.defaults.defaultsval.mflags.reg', desc='regularization value used in the segmentation'); # EPI unwarping for quality check - epi = traits.File(copyfile=False, exists=True, mandatory=True, + epi = File(copyfile=False, exists=True, mandatory=True, field='subj.session.epi', desc='EPI to unwarp'); matchvdm = traits.Bool(True, usedefault=True, field='subj.matchvdm', desc='match VDM to EPI'); - sessname = traits.String('_run-', usedefault=True, + sessname = Str('_run-', usedefault=True, field='subj.sessname', desc='VDM filename extension'); writeunwarped = traits.Bool(False, usedefault=True, field='subj.writeunwarped', desc='write unwarped EPI'); - anat = traits.File(copyfile=False, exists=True, + anat = File(copyfile=False, exists=True, field='subj.anat', desc='anatomical image for comparison'); matchanat = traits.Bool(True, usedefault=True, @@ -115,9 +115,9 @@ class FieldMapOutputSpec(TraitedSpec): class FieldMap(SPMCommand): - """Use spm to calculate fieldmap vdm. + """Use the fieldmap toolbox from spm to calculate the voxel displacement map (VDM). - http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=19 + http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=173 To do ----- @@ -145,9 +145,7 @@ class FieldMap(SPMCommand): def _format_arg(self, opt, spec, val): """Convert input to appropriate format for spm """ - if opt == 'phase' or opt == 'magnitude' or opt == 'anat': - return scans_for_fname(filename_to_list(val)) - if opt == 'epi' or opt == 'magnitude': + if opt in ['phase', 'magnitude', 'anat', 'epi']: return scans_for_fname(filename_to_list(val)) return super(FieldMap, self)._format_arg(opt, spec, val) From 39715f2a7129e03c7e618ba19c15943327c20972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81my=20Guillon?= Date: Wed, 14 Feb 2018 15:40:18 +0100 Subject: [PATCH 3/5] Fix doctest filenames as suggested by @effigies --- nipype/interfaces/spm/preprocess.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/spm/preprocess.py b/nipype/interfaces/spm/preprocess.py index d9cf376b2c..62dc6e9a22 100644 --- a/nipype/interfaces/spm/preprocess.py +++ b/nipype/interfaces/spm/preprocess.py @@ -127,8 +127,8 @@ class FieldMap(SPMCommand): -------- >>> from nipype.interfaces.spm import FieldMap >>> fm = FieldMap() - >>> fm.inputs.phase = 'phasediff.nii' - >>> fm.inputs.magnitude = 'magnitude1.nii' + >>> fm.inputs.phase = 'phase.nii' + >>> fm.inputs.magnitude = 'magnitude.nii' >>> fm.inputs.et = [5.19, 7.65] >>> fm.inputs.blipdir = 1 >>> fm.inputs.tert = 15.6 From c397662a69a152a43ce17d98e3109d28a678d1d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81my=20Guillon?= Date: Fri, 16 Feb 2018 15:56:24 +0100 Subject: [PATCH 4/5] Fix doctest and make vars more explicit --- nipype/interfaces/spm/base.py | 2 ++ nipype/interfaces/spm/preprocess.py | 42 +++++++++++++---------------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/nipype/interfaces/spm/base.py b/nipype/interfaces/spm/base.py index cb0416392a..f3758e4906 100644 --- a/nipype/interfaces/spm/base.py +++ b/nipype/interfaces/spm/base.py @@ -375,6 +375,8 @@ def _format_arg(self, opt, spec, val): """Convert input to appropriate format for SPM.""" if spec.is_trait_type(traits.Bool): return int(val) + elif spec.is_trait_type(traits.Tuple): + return list(val) else: return val diff --git a/nipype/interfaces/spm/preprocess.py b/nipype/interfaces/spm/preprocess.py index 62dc6e9a22..4acb5d2586 100644 --- a/nipype/interfaces/spm/preprocess.py +++ b/nipype/interfaces/spm/preprocess.py @@ -33,35 +33,35 @@ class FieldMapInputSpec(SPMCommandInputSpec): jobtype = traits.Enum('calculatevdm', 'applyvdm', usedefault=True, desc='one of: calculatevdm, applyvdm') - phase = File(mandatory=True, exists=True, copyfile=False, + phase_file = File(mandatory=True, exists=True, copyfile=False, field='subj.data.presubphasemag.phase', desc='presubstracted phase file') - magnitude = File(mandatory=True, exists=True, copyfile=False, + magnitude_file = File(mandatory=True, exists=True, copyfile=False, field='subj.data.presubphasemag.magnitude', desc='presubstracted magnitude file') - et = traits.Tuple(traits.Float, traits.Float, mandatory=True, + echo_times = traits.Tuple(traits.Float, traits.Float, mandatory=True, field='subj.defaults.defaultsval.et', desc='short and long echo times') maskbrain = traits.Bool(True, usedefault=True, field='subj.defaults.defaultsval.maskbrain', desc='masking or no masking of the brain') - blipdir = traits.Enum(1, -1, mandatory=True, + blip_direction = traits.Enum(1, -1, mandatory=True, field='subj.defaults.defaultsval.blipdir', desc='polarity of the phase-encode blips') - tert = traits.Float(mandatory=True, + total_readout_time = traits.Float(mandatory=True, field='subj.defaults.defaultsval.tert', desc='total EPI readout time') epifm = traits.Bool(False, usedefault=True, field='subj.defaults.defaultsval.epifm', desc='epi-based field map'); - ajm = traits.Bool(False, usedefault=True, + jacobian_modulation = traits.Bool(False, usedefault=True, field='subj.defaults.defaultsval.ajm', desc='jacobian modulation'); # Unwarping defaults parameters method = traits.Enum('Mark3D', 'Mark2D', 'Huttonish', usedefault=True, desc='One of: Mark3D, Mark2D, Huttonish', field='subj.defaults.defaultsval.uflags.method'); - fwhm = traits.Range(low=0, value=10, usedefault=True, + unwarp_fwhm = traits.Range(low=0, value=10, usedefault=True, field='subj.defaults.defaultsval.uflags.fwhm', desc='gaussian smoothing kernel width'); pad = traits.Range(low=0, value=0, usedefault=True, @@ -74,7 +74,7 @@ class FieldMapInputSpec(SPMCommandInputSpec): template = File(copyfile=False, exists=True, field='subj.defaults.defaultsval.mflags.template', desc='template image for brain masking'); - fwhm = traits.Range(low=0, value=5, usedefault=True, + mask_fwhm = traits.Range(low=0, value=5, usedefault=True, field='subj.defaults.defaultsval.mflags.fwhm', desc='gaussian smoothing kernel width'); nerode = traits.Range(low=0, value=2, usedefault=True, @@ -90,7 +90,7 @@ class FieldMapInputSpec(SPMCommandInputSpec): field='subj.defaults.defaultsval.mflags.reg', desc='regularization value used in the segmentation'); # EPI unwarping for quality check - epi = File(copyfile=False, exists=True, mandatory=True, + epi_file = File(copyfile=False, exists=True, mandatory=True, field='subj.session.epi', desc='EPI to unwarp'); matchvdm = traits.Bool(True, usedefault=True, @@ -102,7 +102,7 @@ class FieldMapInputSpec(SPMCommandInputSpec): writeunwarped = traits.Bool(False, usedefault=True, field='subj.writeunwarped', desc='write unwarped EPI'); - anat = File(copyfile=False, exists=True, + anat_file = File(copyfile=False, exists=True, field='subj.anat', desc='anatomical image for comparison'); matchanat = traits.Bool(True, usedefault=True, @@ -127,12 +127,12 @@ class FieldMap(SPMCommand): -------- >>> from nipype.interfaces.spm import FieldMap >>> fm = FieldMap() - >>> fm.inputs.phase = 'phase.nii' - >>> fm.inputs.magnitude = 'magnitude.nii' - >>> fm.inputs.et = [5.19, 7.65] - >>> fm.inputs.blipdir = 1 - >>> fm.inputs.tert = 15.6 - >>> fm.inputs.epi = 'bold.nii' + >>> fm.inputs.phase_file = 'phase.nii' + >>> fm.inputs.magnitude_file = 'magnitude.nii' + >>> fm.inputs.echo_times = (5.19, 7.65) + >>> fm.inputs.blip_direction = 1 + >>> fm.inputs.total_readout_time = 15.6 + >>> fm.inputs.epi_file = 'bold.nii' >>> fm.run() # doctest: +SKIP """ @@ -145,7 +145,7 @@ class FieldMap(SPMCommand): def _format_arg(self, opt, spec, val): """Convert input to appropriate format for spm """ - if opt in ['phase', 'magnitude', 'anat', 'epi']: + if opt in ['phase_file', 'magnitude_file', 'anat_file', 'epi_file']: return scans_for_fname(filename_to_list(val)) return super(FieldMap, self)._format_arg(opt, spec, val) @@ -154,17 +154,13 @@ def _parse_inputs(self): """validate spm fieldmap options if set to None ignore """ einputs = super(FieldMap, self)._parse_inputs() - jobtype = self.inputs.jobtype - return [{'%s' % (jobtype): einputs[0]}] + return [{self.inputs.jobtype: einputs[0]}] def _list_outputs(self): outputs = self._outputs().get() jobtype = self.inputs.jobtype if jobtype == "calculatevdm": - outputs['vdm'] = [] - for phase in filename_to_list(self.inputs.phase): - outputs['vdm'].append(fname_presuffix(phase, prefix='vdm5_sc')) - outputs['vdm'] = list_to_filename(outputs['vdm']) + outputs['vdm'] = fname_presuffix(self.inputs.phase_file, prefix='vdm5_sc') return outputs From a4994ef923f7ea56113e00755fa40544ecfd9d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81my=20Guillon?= Date: Mon, 19 Feb 2018 12:18:02 +0100 Subject: [PATCH 5/5] Fix my doctest and add test_auto file --- nipype/interfaces/spm/preprocess.py | 2 +- .../spm/tests/test_auto_FieldMap.py | 133 ++++++++++++++++++ .../interfaces/tests/test_auto_DataGrabber.py | 1 + .../tests/test_auto_SSHDataGrabber.py | 1 + 4 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 nipype/interfaces/spm/tests/test_auto_FieldMap.py diff --git a/nipype/interfaces/spm/preprocess.py b/nipype/interfaces/spm/preprocess.py index 4acb5d2586..1451a55ce4 100644 --- a/nipype/interfaces/spm/preprocess.py +++ b/nipype/interfaces/spm/preprocess.py @@ -132,7 +132,7 @@ class FieldMap(SPMCommand): >>> fm.inputs.echo_times = (5.19, 7.65) >>> fm.inputs.blip_direction = 1 >>> fm.inputs.total_readout_time = 15.6 - >>> fm.inputs.epi_file = 'bold.nii' + >>> fm.inputs.epi_file = 'epi.nii' >>> fm.run() # doctest: +SKIP """ diff --git a/nipype/interfaces/spm/tests/test_auto_FieldMap.py b/nipype/interfaces/spm/tests/test_auto_FieldMap.py new file mode 100644 index 0000000000..b185238a05 --- /dev/null +++ b/nipype/interfaces/spm/tests/test_auto_FieldMap.py @@ -0,0 +1,133 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..preprocess import FieldMap + + +def test_FieldMap_inputs(): + input_map = dict( + anat_file=dict( + copyfile=False, + field='subj.anat', + ), + blip_direction=dict( + field='subj.defaults.defaultsval.blipdir', + mandatory=True, + ), + echo_times=dict( + field='subj.defaults.defaultsval.et', + mandatory=True, + ), + epi_file=dict( + copyfile=False, + field='subj.session.epi', + mandatory=True, + ), + epifm=dict( + field='subj.defaults.defaultsval.epifm', + usedefault=True, + ), + ignore_exception=dict( + deprecated='1.0.0', + nohash=True, + usedefault=True, + ), + jacobian_modulation=dict( + field='subj.defaults.defaultsval.ajm', + usedefault=True, + ), + jobtype=dict(usedefault=True, ), + magnitude_file=dict( + copyfile=False, + field='subj.data.presubphasemag.magnitude', + mandatory=True, + ), + mask_fwhm=dict( + field='subj.defaults.defaultsval.mflags.fwhm', + usedefault=True, + ), + maskbrain=dict( + field='subj.defaults.defaultsval.maskbrain', + usedefault=True, + ), + matchanat=dict( + field='subj.matchanat', + usedefault=True, + ), + matchvdm=dict( + field='subj.matchvdm', + usedefault=True, + ), + matlab_cmd=dict(), + method=dict( + field='subj.defaults.defaultsval.uflags.method', + usedefault=True, + ), + mfile=dict(usedefault=True, ), + ndilate=dict( + field='subj.defaults.defaultsval.mflags.ndilate', + usedefault=True, + ), + nerode=dict( + field='subj.defaults.defaultsval.mflags.nerode', + usedefault=True, + ), + pad=dict( + field='subj.defaults.defaultsval.uflags.pad', + usedefault=True, + ), + paths=dict(), + phase_file=dict( + copyfile=False, + field='subj.data.presubphasemag.phase', + mandatory=True, + ), + reg=dict( + field='subj.defaults.defaultsval.mflags.reg', + usedefault=True, + ), + sessname=dict( + field='subj.sessname', + usedefault=True, + ), + template=dict( + copyfile=False, + field='subj.defaults.defaultsval.mflags.template', + ), + thresh=dict( + field='subj.defaults.defaultsval.mflags.thresh', + usedefault=True, + ), + total_readout_time=dict( + field='subj.defaults.defaultsval.tert', + mandatory=True, + ), + unwarp_fwhm=dict( + field='subj.defaults.defaultsval.uflags.fwhm', + usedefault=True, + ), + use_mcr=dict(), + use_v8struct=dict( + min_ver='8', + usedefault=True, + ), + writeunwarped=dict( + field='subj.writeunwarped', + usedefault=True, + ), + ws=dict( + field='subj.defaults.defaultsval.uflags.ws', + usedefault=True, + ), + ) + inputs = FieldMap.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value +def test_FieldMap_outputs(): + output_map = dict(vdm=dict(), ) + outputs = FieldMap.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/tests/test_auto_DataGrabber.py b/nipype/interfaces/tests/test_auto_DataGrabber.py index e9717fafd5..2705ca7089 100644 --- a/nipype/interfaces/tests/test_auto_DataGrabber.py +++ b/nipype/interfaces/tests/test_auto_DataGrabber.py @@ -6,6 +6,7 @@ def test_DataGrabber_inputs(): input_map = dict( base_directory=dict(), + drop_blank_outputs=dict(usedefault=True, ), ignore_exception=dict( deprecated='1.0.0', nohash=True, diff --git a/nipype/interfaces/tests/test_auto_SSHDataGrabber.py b/nipype/interfaces/tests/test_auto_SSHDataGrabber.py index cef48fa7c6..3a0e65efd6 100644 --- a/nipype/interfaces/tests/test_auto_SSHDataGrabber.py +++ b/nipype/interfaces/tests/test_auto_SSHDataGrabber.py @@ -7,6 +7,7 @@ def test_SSHDataGrabber_inputs(): input_map = dict( base_directory=dict(mandatory=True, ), download_files=dict(usedefault=True, ), + drop_blank_outputs=dict(usedefault=True, ), hostname=dict(mandatory=True, ), ignore_exception=dict( deprecated='1.0.0',