From 3008a679063fa4fd2b65a7c644d86bf28085a90d Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Mon, 26 May 2025 10:42:49 +0200 Subject: [PATCH 01/14] Update BIDS data grabbing to grab only anatomical and PET data (no functional) --- niworkflows/interfaces/bids.py | 9 ++------- niworkflows/utils/bids.py | 15 +++------------ 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/niworkflows/interfaces/bids.py b/niworkflows/interfaces/bids.py index 84c50f10f6e..50e35b046b9 100644 --- a/niworkflows/interfaces/bids.py +++ b/niworkflows/interfaces/bids.py @@ -260,7 +260,7 @@ class BIDSDataGrabber(SimpleInterface): input_spec = _BIDSDataGrabberInputSpec output_spec = _BIDSDataGrabberOutputSpec - _require_funcs = True + _require_funcs = False def __init__(self, *args, **kwargs): anat_only = kwargs.pop('anat_only', None) @@ -282,12 +282,7 @@ def _run_interface(self, runtime): f'No T1w images found for subject sub-{self.inputs.subject_id}' ) - if self._require_funcs and not bids_dict['bold']: - raise FileNotFoundError( - f'No functional images found for subject sub-{self.inputs.subject_id}' - ) - - for imtype in ['bold', 't2w', 'flair', 'fmap', 'sbref', 'roi', 'pet', 'asl']: + for imtype in ['t2w', 'flair', 'fmap', 'sbref', 'roi', 'pet', 'asl']: if not bids_dict[imtype]: LOGGER.info('No "%s" images found for sub-%s', imtype, self.inputs.subject_id) diff --git a/niworkflows/utils/bids.py b/niworkflows/utils/bids.py index 573d7483389..e982b2ef9cb 100644 --- a/niworkflows/utils/bids.py +++ b/niworkflows/utils/bids.py @@ -41,7 +41,7 @@ 'pet': {'suffix': 'pet'}, 'roi': {'datatype': 'anat', 'suffix': 'roi'}, 'sbref': {'datatype': 'func', 'suffix': 'sbref', 'part': ['mag', None]}, - 't1w': {'datatype': 'anat', 'suffix': 'T1w', 'part': ['mag', None]}, + 't1w': {'suffix': 'T1w'}, 't2w': {'datatype': 'anat', 'suffix': 'T2w', 'part': ['mag', None]}, 'asl': {'datatype': 'perf', 'suffix': 'asl'}, } @@ -251,8 +251,9 @@ def collect_data( 'return_type': 'file', 'subject': participant_label, 'extension': ['.nii', '.nii.gz'], - 'session': session_id or Query.OPTIONAL, } + if session_id is not None: + layout_get_kwargs['session'] = session_id reserved_entities = [('subject', participant_label), ('session', session_id)] @@ -271,20 +272,10 @@ def collect_data( # avoid clobbering layout.get del layout_get_kwargs[entity] - if task: - queries['bold']['task'] = task - - if echo: - queries['bold']['echo'] = echo - subj_data = { dtype: sorted(layout.get(**layout_get_kwargs, **query)) for dtype, query in queries.items() } - # Special case: multi-echo BOLD, grouping echos - if group_echos and 'bold' in subj_data and any('_echo-' in bold for bold in subj_data['bold']): - subj_data['bold'] = group_multiecho(subj_data['bold']) - return subj_data, layout From 845a31d3e0f56cfb2bd91d6f405e1fb4b9139408 Mon Sep 17 00:00:00 2001 From: Martin Norgaard Date: Fri, 6 Jun 2025 12:01:19 +0200 Subject: [PATCH 02/14] Update niworkflows/interfaces/bids.py Co-authored-by: Mathias Goncalves --- niworkflows/interfaces/bids.py | 1 - 1 file changed, 1 deletion(-) diff --git a/niworkflows/interfaces/bids.py b/niworkflows/interfaces/bids.py index 50e35b046b9..c51291e22c0 100644 --- a/niworkflows/interfaces/bids.py +++ b/niworkflows/interfaces/bids.py @@ -260,7 +260,6 @@ class BIDSDataGrabber(SimpleInterface): input_spec = _BIDSDataGrabberInputSpec output_spec = _BIDSDataGrabberOutputSpec - _require_funcs = False def __init__(self, *args, **kwargs): anat_only = kwargs.pop('anat_only', None) From 725d2a47783da163a62df1ebebfa04e7d3db79b0 Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 12:05:09 +0200 Subject: [PATCH 03/14] FIX: re-add require funcs check --- niworkflows/interfaces/bids.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/niworkflows/interfaces/bids.py b/niworkflows/interfaces/bids.py index c51291e22c0..569b6668ca6 100644 --- a/niworkflows/interfaces/bids.py +++ b/niworkflows/interfaces/bids.py @@ -280,6 +280,11 @@ def _run_interface(self, runtime): raise FileNotFoundError( f'No T1w images found for subject sub-{self.inputs.subject_id}' ) + + if self._require_funcs and not bids_dict['bold']: + raise FileNotFoundError( + f'No functional images found for subject sub-{self.inputs.subject_id}' + ) for imtype in ['t2w', 'flair', 'fmap', 'sbref', 'roi', 'pet', 'asl']: if not bids_dict[imtype]: From 09ec62cf23f1daf533150bbfd189e39d44af4d76 Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 12:08:33 +0200 Subject: [PATCH 04/14] FIX: add require_funcs to init --- niworkflows/interfaces/bids.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/niworkflows/interfaces/bids.py b/niworkflows/interfaces/bids.py index 569b6668ca6..2ea4d43606d 100644 --- a/niworkflows/interfaces/bids.py +++ b/niworkflows/interfaces/bids.py @@ -261,11 +261,12 @@ class BIDSDataGrabber(SimpleInterface): input_spec = _BIDSDataGrabberInputSpec output_spec = _BIDSDataGrabberOutputSpec - def __init__(self, *args, **kwargs): + def __init__(self, *args, require_funcs=False, **kwargs): anat_only = kwargs.pop('anat_only', None) anat_derivatives = kwargs.pop('anat_derivatives', None) require_t1w = kwargs.pop('require_t1w', True) super().__init__(*args, **kwargs) + self._require_funcs = require_funcs if anat_only is not None: self._require_funcs = not anat_only self._require_t1w = require_t1w and anat_derivatives is None From eadcf3ec84aa34b6f247797e8deacbba5520b2b6 Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 13:05:34 +0200 Subject: [PATCH 05/14] FIX: update BIDS datagrabber to grab PET data --- niworkflows/interfaces/bids.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/niworkflows/interfaces/bids.py b/niworkflows/interfaces/bids.py index 2ea4d43606d..e742d07ff49 100644 --- a/niworkflows/interfaces/bids.py +++ b/niworkflows/interfaces/bids.py @@ -261,14 +261,26 @@ class BIDSDataGrabber(SimpleInterface): input_spec = _BIDSDataGrabberInputSpec output_spec = _BIDSDataGrabberOutputSpec - def __init__(self, *args, require_funcs=False, **kwargs): + def __init__(self, *args, **kwargs): anat_only = kwargs.pop('anat_only', None) anat_derivatives = kwargs.pop('anat_derivatives', None) require_t1w = kwargs.pop('require_t1w', True) + require_funcs = kwargs.pop('require_funcs', True) + require_pet = kwargs.pop('require_pet', False) super().__init__(*args, **kwargs) - self._require_funcs = require_funcs + if anat_only is not None: self._require_funcs = not anat_only + self._require_pet = False + else: + # Automatically set require_funcs=False if PET data is present + if require_pet: + self._require_funcs = False + self._require_pet = True + else: + self._require_funcs = require_funcs + self._require_pet = False + self._require_t1w = require_t1w and anat_derivatives is None def _run_interface(self, runtime): @@ -286,6 +298,11 @@ def _run_interface(self, runtime): raise FileNotFoundError( f'No functional images found for subject sub-{self.inputs.subject_id}' ) + + if self._require_pet and not bids_dict.get('pet'): + raise FileNotFoundError( + f'No PET images found for subject sub-{self.inputs.subject_id}' + ) for imtype in ['t2w', 'flair', 'fmap', 'sbref', 'roi', 'pet', 'asl']: if not bids_dict[imtype]: From 36517e02b163b2df10bdfe65027bbabf138c0570 Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 13:05:51 +0200 Subject: [PATCH 06/14] FIX: add test for grabbing pet and/or functional data --- niworkflows/interfaces/tests/test_bids.py | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/niworkflows/interfaces/tests/test_bids.py b/niworkflows/interfaces/tests/test_bids.py index 5da592f8ece..11f444916cb 100644 --- a/niworkflows/interfaces/tests/test_bids.py +++ b/niworkflows/interfaces/tests/test_bids.py @@ -806,3 +806,27 @@ def test_BIDSDataGrabber(): x = bintfs.BIDSDataGrabber(anat_derivatives='derivatives') assert x._require_t1w is False + + +def test_require_func_pet_behavior(): + from niworkflows.interfaces.bids import BIDSDataGrabber + import pytest + + subject_data_pet = {'t1w': ['t1.nii'], 'bold': [], 'pet': ['pet.nii']} + subject_data_bold = {'t1w': ['t1.nii'], 'bold': ['bold.nii'], 'pet': []} + + # PET present, functional not required + grabber_pet = BIDSDataGrabber(subject_data=subject_data_pet, subject_id='01', require_pet=True) + assert grabber_pet._require_funcs is False + assert grabber_pet._require_pet is True + grabber_pet.run() # Should succeed without bold data + + # PET absent, functional required by default + grabber_func = BIDSDataGrabber(subject_data=subject_data_bold, subject_id='01') + assert grabber_func._require_funcs is True + grabber_func.run() # Should succeed with bold data + + # Fail when bold is required but missing + grabber_fail = BIDSDataGrabber(subject_data=subject_data_pet, subject_id='01') + with pytest.raises(FileNotFoundError, match='No functional images found'): + grabber_fail.run() From f973869ac4f615770487632de02c72063dc28e93 Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 13:28:52 +0200 Subject: [PATCH 07/14] FIX: update data grabber --- niworkflows/interfaces/bids.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/niworkflows/interfaces/bids.py b/niworkflows/interfaces/bids.py index e742d07ff49..a0418bbf939 100644 --- a/niworkflows/interfaces/bids.py +++ b/niworkflows/interfaces/bids.py @@ -269,17 +269,12 @@ def __init__(self, *args, **kwargs): require_pet = kwargs.pop('require_pet', False) super().__init__(*args, **kwargs) - if anat_only is not None: - self._require_funcs = not anat_only + if anat_only: + self._require_funcs = False self._require_pet = False else: - # Automatically set require_funcs=False if PET data is present - if require_pet: - self._require_funcs = False - self._require_pet = True - else: - self._require_funcs = require_funcs - self._require_pet = False + self._require_funcs = False if require_pet else require_funcs + self._require_pet = require_pet self._require_t1w = require_t1w and anat_derivatives is None From 9d82f5ab23d2b3a2b9a9679372f9051a285130d4 Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 13:54:33 +0200 Subject: [PATCH 08/14] FIX: fix test to include all data types to avoid KeyError --- niworkflows/interfaces/tests/test_bids.py | 27 ++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/niworkflows/interfaces/tests/test_bids.py b/niworkflows/interfaces/tests/test_bids.py index 11f444916cb..691fde7a818 100644 --- a/niworkflows/interfaces/tests/test_bids.py +++ b/niworkflows/interfaces/tests/test_bids.py @@ -812,8 +812,29 @@ def test_require_func_pet_behavior(): from niworkflows.interfaces.bids import BIDSDataGrabber import pytest - subject_data_pet = {'t1w': ['t1.nii'], 'bold': [], 'pet': ['pet.nii']} - subject_data_bold = {'t1w': ['t1.nii'], 'bold': ['bold.nii'], 'pet': []} + subject_data_pet = { + 't1w': ['t1.nii'], + 'bold': [], + 'pet': ['pet.nii'], + 't2w': [], + 'flair': [], + 'fmap': [], + 'sbref': [], + 'roi': [], + 'asl': [], + } + + subject_data_bold = { + 't1w': ['t1.nii'], + 'bold': ['bold.nii'], + 'pet': [], + 't2w': [], + 'flair': [], + 'fmap': [], + 'sbref': [], + 'roi': [], + 'asl': [], + } # PET present, functional not required grabber_pet = BIDSDataGrabber(subject_data=subject_data_pet, subject_id='01', require_pet=True) @@ -829,4 +850,4 @@ def test_require_func_pet_behavior(): # Fail when bold is required but missing grabber_fail = BIDSDataGrabber(subject_data=subject_data_pet, subject_id='01') with pytest.raises(FileNotFoundError, match='No functional images found'): - grabber_fail.run() + grabber_fail.run() \ No newline at end of file From 42cb1a2424e4ce7a9d95bee39dca3d3e40ce649b Mon Sep 17 00:00:00 2001 From: mathiasg Date: Fri, 6 Jun 2025 11:28:54 -0400 Subject: [PATCH 09/14] ENH: Generalize `require` for all image types --- niworkflows/interfaces/bids.py | 54 ++++++++++------------- niworkflows/interfaces/tests/test_bids.py | 25 ++++++----- 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/niworkflows/interfaces/bids.py b/niworkflows/interfaces/bids.py index a0418bbf939..27277e4ddf3 100644 --- a/niworkflows/interfaces/bids.py +++ b/niworkflows/interfaces/bids.py @@ -261,22 +261,28 @@ class BIDSDataGrabber(SimpleInterface): input_spec = _BIDSDataGrabberInputSpec output_spec = _BIDSDataGrabberOutputSpec - def __init__(self, *args, **kwargs): - anat_only = kwargs.pop('anat_only', None) - anat_derivatives = kwargs.pop('anat_derivatives', None) - require_t1w = kwargs.pop('require_t1w', True) - require_funcs = kwargs.pop('require_funcs', True) - require_pet = kwargs.pop('require_pet', False) - super().__init__(*args, **kwargs) - + _image_types = {'asl', 'bold', 'dwi', 'flair', 'fmap', 'pet', 'roi', 'sbref', 't1w', 't2w'} + + def __init__( + self, + anat_only=False, + anat_derivatives=None, + *args, + **kwargs, + ): + default_required = {'t1w', 'bold'} + + for imtype in self._image_types: + kwarg = f'require_{imtype}' + val = kwargs.pop(kwarg, True if imtype in default_required else False) + setattr(self, f'_{kwarg}', val) + + self._require_t1w = self._require_t1w and anat_derivatives is None if anat_only: - self._require_funcs = False + self._require_bold = False self._require_pet = False - else: - self._require_funcs = False if require_pet else require_funcs - self._require_pet = require_pet - self._require_t1w = require_t1w and anat_derivatives is None + super().__init__(*args, **kwargs) def _run_interface(self, runtime): bids_dict = self.inputs.subject_data @@ -284,24 +290,12 @@ def _run_interface(self, runtime): self._results['out_dict'] = bids_dict self._results.update(bids_dict) - if self._require_t1w and not bids_dict['t1w']: - raise FileNotFoundError( - f'No T1w images found for subject sub-{self.inputs.subject_id}' - ) - - if self._require_funcs and not bids_dict['bold']: - raise FileNotFoundError( - f'No functional images found for subject sub-{self.inputs.subject_id}' - ) - - if self._require_pet and not bids_dict.get('pet'): - raise FileNotFoundError( - f'No PET images found for subject sub-{self.inputs.subject_id}' - ) - - for imtype in ['t2w', 'flair', 'fmap', 'sbref', 'roi', 'pet', 'asl']: + for imtype in self._image_types: if not bids_dict[imtype]: - LOGGER.info('No "%s" images found for sub-%s', imtype, self.inputs.subject_id) + msg = f'No "{imtype}" images found for sub-{self.inputs.subject_id}' + if getattr(self, f'_require_{imtype}', False): # only raise if image is required + raise FileNotFoundError(msg) + LOGGER.info(msg) return runtime diff --git a/niworkflows/interfaces/tests/test_bids.py b/niworkflows/interfaces/tests/test_bids.py index 691fde7a818..9d6b16ef15a 100644 --- a/niworkflows/interfaces/tests/test_bids.py +++ b/niworkflows/interfaces/tests/test_bids.py @@ -798,20 +798,21 @@ def test_fsdir_min_version(tmp_path, min_version): def test_BIDSDataGrabber(): x = bintfs.BIDSDataGrabber(anat_only=True) assert x._require_t1w is True - assert x._require_funcs is False + assert x._require_bold is False x = bintfs.BIDSDataGrabber(anat_only=False, require_t1w=False) assert x._require_t1w is False - assert x._require_funcs is True + assert x._require_bold is True x = bintfs.BIDSDataGrabber(anat_derivatives='derivatives') assert x._require_t1w is False -def test_require_func_pet_behavior(): - from niworkflows.interfaces.bids import BIDSDataGrabber +def test_require_bold_pet_behavior(): import pytest + from niworkflows.interfaces.bids import BIDSDataGrabber + subject_data_pet = { 't1w': ['t1.nii'], 'bold': [], @@ -822,6 +823,7 @@ def test_require_func_pet_behavior(): 'sbref': [], 'roi': [], 'asl': [], + 'dwi': [], } subject_data_bold = { @@ -834,20 +836,23 @@ def test_require_func_pet_behavior(): 'sbref': [], 'roi': [], 'asl': [], + 'dwi': [], } # PET present, functional not required - grabber_pet = BIDSDataGrabber(subject_data=subject_data_pet, subject_id='01', require_pet=True) - assert grabber_pet._require_funcs is False + grabber_pet = BIDSDataGrabber( + subject_data=subject_data_pet, subject_id='01', require_pet=True, require_bold=False + ) + assert grabber_pet._require_bold is False assert grabber_pet._require_pet is True grabber_pet.run() # Should succeed without bold data # PET absent, functional required by default grabber_func = BIDSDataGrabber(subject_data=subject_data_bold, subject_id='01') - assert grabber_func._require_funcs is True - grabber_func.run() # Should succeed with bold data + assert grabber_func._require_bold is True + assert grabber_func.run().outputs.bold == 'bold.nii' # Fail when bold is required but missing grabber_fail = BIDSDataGrabber(subject_data=subject_data_pet, subject_id='01') - with pytest.raises(FileNotFoundError, match='No functional images found'): - grabber_fail.run() \ No newline at end of file + with pytest.raises(FileNotFoundError, match='No "bold" images found'): + grabber_fail.run() From b9216e769b1ac2cde238bb7ec2cb7fee9be61c36 Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 19:41:38 +0200 Subject: [PATCH 10/14] FIX: re-add T1w info to DEFAULT_BIDS_QUERIES --- niworkflows/utils/bids.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/niworkflows/utils/bids.py b/niworkflows/utils/bids.py index e982b2ef9cb..d3a68bbfec8 100644 --- a/niworkflows/utils/bids.py +++ b/niworkflows/utils/bids.py @@ -41,7 +41,7 @@ 'pet': {'suffix': 'pet'}, 'roi': {'datatype': 'anat', 'suffix': 'roi'}, 'sbref': {'datatype': 'func', 'suffix': 'sbref', 'part': ['mag', None]}, - 't1w': {'suffix': 'T1w'}, + 't1w': {'datatype': 'anat', 'suffix': 'T1w', 'part': ['mag', None]}, 't2w': {'datatype': 'anat', 'suffix': 'T2w', 'part': ['mag', None]}, 'asl': {'datatype': 'perf', 'suffix': 'asl'}, } From a098cec56ff4e0717f273df76cf0429750180773 Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 19:43:17 +0200 Subject: [PATCH 11/14] FIX: revert change on session --- niworkflows/utils/bids.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/niworkflows/utils/bids.py b/niworkflows/utils/bids.py index d3a68bbfec8..ccf9410a3b7 100644 --- a/niworkflows/utils/bids.py +++ b/niworkflows/utils/bids.py @@ -252,8 +252,6 @@ def collect_data( 'subject': participant_label, 'extension': ['.nii', '.nii.gz'], } - if session_id is not None: - layout_get_kwargs['session'] = session_id reserved_entities = [('subject', participant_label), ('session', session_id)] From 0cb2bf77fadd143dfbfb5a40be41c4f993989f9d Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 19:46:02 +0200 Subject: [PATCH 12/14] FIX: revert changes --- niworkflows/utils/bids.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/niworkflows/utils/bids.py b/niworkflows/utils/bids.py index ccf9410a3b7..cd86f1bfc19 100644 --- a/niworkflows/utils/bids.py +++ b/niworkflows/utils/bids.py @@ -274,6 +274,10 @@ def collect_data( dtype: sorted(layout.get(**layout_get_kwargs, **query)) for dtype, query in queries.items() } + # Special case: multi-echo BOLD, grouping echos + if group_echos and 'bold' in subj_data and any('_echo-' in bold for bold in subj_data['bold']): + subj_data['bold'] = group_multiecho(subj_data['bold']) + return subj_data, layout From 0cc7f809c141a14e550f3749378940380396140c Mon Sep 17 00:00:00 2001 From: mnoergaard Date: Fri, 6 Jun 2025 19:49:34 +0200 Subject: [PATCH 13/14] FIX: apply suggestion from code review --- niworkflows/utils/bids.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/niworkflows/utils/bids.py b/niworkflows/utils/bids.py index cd86f1bfc19..b0a658db78a 100644 --- a/niworkflows/utils/bids.py +++ b/niworkflows/utils/bids.py @@ -34,7 +34,13 @@ from packaging.version import Version DEFAULT_BIDS_QUERIES = { - 'bold': {'datatype': 'func', 'suffix': 'bold', 'part': ['mag', None]}, + 'bold': { + 'datatype': 'func', + 'suffix': 'bold', + 'part': ['mag', None], + 'task': Query.OPTIONAL, + 'echo': Query.OPTIONAL, + }, 'dwi': {'suffix': 'dwi'}, 'flair': {'datatype': 'anat', 'suffix': 'FLAIR', 'part': ['mag', None]}, 'fmap': {'datatype': 'fmap'}, @@ -270,6 +276,12 @@ def collect_data( # avoid clobbering layout.get del layout_get_kwargs[entity] + if task: + queries['bold']['task'] = task + + if echo: + queries['bold']['echo'] = echo + subj_data = { dtype: sorted(layout.get(**layout_get_kwargs, **query)) for dtype, query in queries.items() } From 9fd80dc13e799eb522bbcadb07d80aa34665bee1 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Fri, 6 Jun 2025 14:44:12 -0400 Subject: [PATCH 14/14] fix: apply task to pet query --- niworkflows/utils/bids.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/niworkflows/utils/bids.py b/niworkflows/utils/bids.py index b0a658db78a..5d9fab3d3c2 100644 --- a/niworkflows/utils/bids.py +++ b/niworkflows/utils/bids.py @@ -35,11 +35,9 @@ DEFAULT_BIDS_QUERIES = { 'bold': { - 'datatype': 'func', - 'suffix': 'bold', + 'datatype': 'func', + 'suffix': 'bold', 'part': ['mag', None], - 'task': Query.OPTIONAL, - 'echo': Query.OPTIONAL, }, 'dwi': {'suffix': 'dwi'}, 'flair': {'datatype': 'anat', 'suffix': 'FLAIR', 'part': ['mag', None]}, @@ -257,6 +255,7 @@ def collect_data( 'return_type': 'file', 'subject': participant_label, 'extension': ['.nii', '.nii.gz'], + 'session': session_id or Query.OPTIONAL, } reserved_entities = [('subject', participant_label), ('session', session_id)] @@ -277,7 +276,7 @@ def collect_data( del layout_get_kwargs[entity] if task: - queries['bold']['task'] = task + queries['bold']['task'] = queries['pet']['task'] = task if echo: queries['bold']['echo'] = echo