diff --git a/.travis.yml b/.travis.yml index 6ebe0821fc..645d6c623b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,8 +89,8 @@ before_install: fi; - travis_retry pip install -r requirements.txt -- travis_retry pip install grabbit==0.1.2 -- travis_retry git clone -b 0.6.5 https://github.com/INCF/pybids.git ${HOME}/pybids && pip install -e ${HOME}/pybids +- travis_retry pip install grabbit==0.2.6 +- travis_retry pip install -e git+https://github.com/bids-standard/pybids.git@0.7.0#egg=pybids install: - travis_retry pip install $EXTRA_PIP_FLAGS -e .[$NIPYPE_EXTRAS] diff --git a/docker/generate_dockerfiles.sh b/docker/generate_dockerfiles.sh index cbe26d05a8..9e6ae4ed11 100755 --- a/docker/generate_dockerfiles.sh +++ b/docker/generate_dockerfiles.sh @@ -107,7 +107,7 @@ function generate_main_dockerfile() { --user neuro \ --miniconda use_env=neuro \ pip_opts="-e" \ - pip_install="/src/nipype[all]" \ + pip_install="/src/nipype[all] https://github.com/bids-standard/pybids/tarball/0.7.0" \ --workdir /work \ --label org.label-schema.build-date='$BUILD_DATE' \ org.label-schema.name="NIPYPE" \ diff --git a/nipype/info.py b/nipype/info.py index 2dd5489e0a..9251de88a7 100644 --- a/nipype/info.py +++ b/nipype/info.py @@ -172,7 +172,7 @@ def get_nipype_gitversion(): 'profiler': ['psutil>=5.0'], 'duecredit': ['duecredit'], 'xvfbwrapper': ['xvfbwrapper'], - 'pybids': ['pybids==0.6.5'], + 'pybids': ['pybids>=0.7.0'], 'ssh': ['paramiko'], # 'mesh': ['mayavi'] # Enable when it works } diff --git a/nipype/interfaces/fsl/tests/test_auto_EddyQuad.py b/nipype/interfaces/fsl/tests/test_auto_EddyQuad.py new file mode 100644 index 0000000000..4302cdc312 --- /dev/null +++ b/nipype/interfaces/fsl/tests/test_auto_EddyQuad.py @@ -0,0 +1,65 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..epi import EddyQuad + + +def test_EddyQuad_inputs(): + input_map = dict( + args=dict(argstr='%s', ), + base_name=dict( + argstr='%s', + position=0, + usedefault=True, + ), + bval_file=dict( + argstr='--bvals=%s', + mandatory=True, + ), + bvec_file=dict(argstr='--bvecs=%s', ), + environ=dict( + nohash=True, + usedefault=True, + ), + field=dict(argstr='--field=%s', ), + idx_file=dict( + argstr='--eddyIdx=%s', + mandatory=True, + ), + mask_file=dict( + argstr='--mask=%s', + mandatory=True, + ), + output_dir=dict( + argstr='--output-dir=%s', + name_source=['base_name'], + name_template='%s.qc', + ), + output_type=dict(), + param_file=dict( + argstr='--eddyParams=%s', + mandatory=True, + ), + slice_spec=dict(argstr='--slspec=%s', ), + verbose=dict(argstr='--verbose', ), + ) + inputs = EddyQuad.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_EddyQuad_outputs(): + output_map = dict( + avg_b0_pe_png=dict(), + avg_b_png=dict(), + clean_volumes=dict(), + cnr_png=dict(), + qc_json=dict(), + qc_pdf=dict(), + residuals=dict(), + vdm_png=dict(), + ) + outputs = EddyQuad.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/io.py b/nipype/interfaces/io.py index e11ba47479..c90aa55315 100644 --- a/nipype/interfaces/io.py +++ b/nipype/interfaces/io.py @@ -2721,18 +2721,23 @@ def _list_outputs(self): class BIDSDataGrabberInputSpec(DynamicTraitedSpec): - base_dir = Directory(exists=True, - desc='Path to BIDS Directory.', - mandatory=True) - output_query = traits.Dict(key_trait=Str, - value_trait=traits.Dict, - desc='Queries for outfield outputs') - raise_on_empty = traits.Bool(True, usedefault=True, - desc='Generate exception if list is empty ' - 'for a given field') - return_type = traits.Enum('file', 'namedtuple', usedefault=True) - strict = traits.Bool(desc='Return only BIDS "proper" files (e.g., ' - 'ignore derivatives/, sourcedata/, etc.)') + base_dir = Directory( + exists=True, + desc='Path to BIDS Directory.', + mandatory=True) + output_query = traits.Dict( + key_trait=Str, + value_trait=traits.Dict, + desc='Queries for outfield outputs') + raise_on_empty = traits.Bool( + True, usedefault=True, + desc='Generate exception if list is empty for a given field') + index_derivatives = traits.Bool( + False, mandatory=True, usedefault=True, + desc='Index derivatives/ sub-directory') + extra_derivatives = traits.List( + Directory(exists=True), + desc='Additional derivative directories to index') class BIDSDataGrabber(LibraryBaseInterface, IOBase): @@ -2758,10 +2763,10 @@ class BIDSDataGrabber(LibraryBaseInterface, IOBase): are filtered on common entities, which can be explicitly defined as infields. - >>> bg = BIDSDataGrabber(infields = ['subject'], outfields = ['dwi']) + >>> bg = BIDSDataGrabber(infields = ['subject']) >>> bg.inputs.base_dir = 'ds005/' >>> bg.inputs.subject = '01' - >>> bg.inputs.output_query['dwi'] = dict(modality='dwi') + >>> bg.inputs.output_query['dwi'] = dict(datatype='dwi') >>> results = bg.run() # doctest: +SKIP """ @@ -2781,18 +2786,17 @@ def __init__(self, infields=None, **kwargs): if not isdefined(self.inputs.output_query): self.inputs.output_query = { - "func": {"modality": "func", 'extensions': ['nii', '.nii.gz']}, - "anat": {"modality": "anat", 'extensions': ['nii', '.nii.gz']}, + "bold": {"datatype": "func", "suffix": "bold", + "extensions": ["nii", ".nii.gz"]}, + "T1w": {"datatype": "anat", "suffix": "T1w", + "extensions": ["nii", ".nii.gz"]}, } # If infields is empty, use all BIDS entities if infields is None: - # Version resilience - try: - from bids import layout as bidslayout - except ImportError: - from bids import grabbids as bidslayout - bids_config = join(dirname(bidslayout.__file__), 'config', 'bids.json') + from bids import layout as bidslayout + bids_config = join( + dirname(bidslayout.__file__), 'config', 'bids.json') bids_config = json.load(open(bids_config, 'r')) infields = [i['name'] for i in bids_config['entities']] @@ -2807,15 +2811,12 @@ def __init__(self, infields=None, **kwargs): self.inputs.trait_set(trait_change_notify=False, **undefined_traits) def _list_outputs(self): - # Version resilience - try: - from bids import BIDSLayout - except ImportError: - from bids.grabbids import BIDSLayout - exclude = None - if self.inputs.strict: - exclude = ['derivatives/', 'code/', 'sourcedata/'] - layout = BIDSLayout(self.inputs.base_dir, exclude=exclude) + from bids import BIDSLayout + layout = BIDSLayout(self.inputs.base_dir, + derivatives=self.inputs.index_derivatives) + + if isdefined(self.inputs.extra_derivatives): + layout.add_derivatives(self.inputs.extra_derivatives) # If infield is not given nm input value, silently ignore filters = {} @@ -2828,7 +2829,7 @@ def _list_outputs(self): for key, query in self.inputs.output_query.items(): args = query.copy() args.update(filters) - filelist = layout.get(return_type=self.inputs.return_type, **args) + filelist = layout.get(return_type='file', **args) if len(filelist) == 0: msg = 'Output key: %s returned no files' % key if self.inputs.raise_on_empty: diff --git a/nipype/interfaces/tests/test_auto_BIDSDataGrabber.py b/nipype/interfaces/tests/test_auto_BIDSDataGrabber.py index 8acdcc9787..24cbda657b 100644 --- a/nipype/interfaces/tests/test_auto_BIDSDataGrabber.py +++ b/nipype/interfaces/tests/test_auto_BIDSDataGrabber.py @@ -6,10 +6,13 @@ def test_BIDSDataGrabber_inputs(): input_map = dict( base_dir=dict(mandatory=True, ), + extra_derivatives=dict(), + index_derivatives=dict( + mandatory=True, + usedefault=True, + ), output_query=dict(), raise_on_empty=dict(usedefault=True, ), - return_type=dict(usedefault=True, ), - strict=dict(), ) inputs = BIDSDataGrabber.input_spec() diff --git a/nipype/interfaces/tests/test_io.py b/nipype/interfaces/tests/test_io.py index c81e6f8e06..4420e4a49c 100644 --- a/nipype/interfaces/tests/test_io.py +++ b/nipype/interfaces/tests/test_io.py @@ -581,8 +581,6 @@ def test_jsonsink(tmpdir, inputs_attributes): # There are three reasons these tests will be skipped: @pytest.mark.skipif(not have_pybids, reason="Pybids is not installed") -@pytest.mark.skipif(sys.version_info < (3, 0), - reason="Pybids no longer supports Python 2") @pytest.mark.skipif(not dist_is_editable('pybids'), reason="Pybids is not installed in editable mode") def test_bids_grabber(tmpdir): @@ -591,15 +589,13 @@ def test_bids_grabber(tmpdir): bg.inputs.base_dir = os.path.join(datadir, 'ds005') bg.inputs.subject = '01' results = bg.run() - assert 'sub-01_T1w.nii.gz' in map(os.path.basename, results.outputs.anat) + assert 'sub-01_T1w.nii.gz' in map(os.path.basename, results.outputs.T1w) assert 'sub-01_task-mixedgamblestask_run-01_bold.nii.gz' in \ - map(os.path.basename, results.outputs.func) + map(os.path.basename, results.outputs.bold) @pytest.mark.skipif(not have_pybids, reason="Pybids is not installed") -@pytest.mark.skipif(sys.version_info < (3, 0), - reason="Pybids no longer supports Python 2") @pytest.mark.skipif(not dist_is_editable('pybids'), reason="Pybids is not installed in editable mode") def test_bids_fields(tmpdir): @@ -607,15 +603,13 @@ def test_bids_fields(tmpdir): bg = nio.BIDSDataGrabber(infields = ['subject'], outfields = ['dwi']) bg.inputs.base_dir = os.path.join(datadir, 'ds005') bg.inputs.subject = '01' - bg.inputs.output_query['dwi'] = dict(modality='dwi') + bg.inputs.output_query['dwi'] = dict(datatype='dwi') results = bg.run() assert 'sub-01_dwi.nii.gz' in map(os.path.basename, results.outputs.dwi) @pytest.mark.skipif(not have_pybids, reason="Pybids is not installed") -@pytest.mark.skipif(sys.version_info < (3, 0), - reason="Pybids no longer supports Python 2") @pytest.mark.skipif(not dist_is_editable('pybids'), reason="Pybids is not installed in editable mode") def test_bids_infields_outfields(tmpdir): @@ -633,9 +627,9 @@ def test_bids_infields_outfields(tmpdir): for outfield in outfields: assert(outfield in bg._outputs().traits()) - # now try without defining outfields, we should get anat and func for free + # now try without defining outfields bg = nio.BIDSDataGrabber() - for outfield in ['anat', 'func']: + for outfield in ['T1w', 'bold']: assert outfield in bg._outputs().traits()