Skip to content

Commit d118beb

Browse files
authored
Merge pull request #951 from nipreps/update_bids_pet
ENH: Toggle requirement for any image type BIDSDataGrabber, add task filtering when collecting PET data
2 parents 37a8147 + 9fd80dc commit d118beb

File tree

3 files changed

+84
-24
lines changed

3 files changed

+84
-24
lines changed

niworkflows/interfaces/bids.py

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -260,36 +260,42 @@ class BIDSDataGrabber(SimpleInterface):
260260

261261
input_spec = _BIDSDataGrabberInputSpec
262262
output_spec = _BIDSDataGrabberOutputSpec
263-
_require_funcs = True
264263

265-
def __init__(self, *args, **kwargs):
266-
anat_only = kwargs.pop('anat_only', None)
267-
anat_derivatives = kwargs.pop('anat_derivatives', None)
268-
require_t1w = kwargs.pop('require_t1w', True)
264+
_image_types = {'asl', 'bold', 'dwi', 'flair', 'fmap', 'pet', 'roi', 'sbref', 't1w', 't2w'}
265+
266+
def __init__(
267+
self,
268+
anat_only=False,
269+
anat_derivatives=None,
270+
*args,
271+
**kwargs,
272+
):
273+
default_required = {'t1w', 'bold'}
274+
275+
for imtype in self._image_types:
276+
kwarg = f'require_{imtype}'
277+
val = kwargs.pop(kwarg, True if imtype in default_required else False)
278+
setattr(self, f'_{kwarg}', val)
279+
280+
self._require_t1w = self._require_t1w and anat_derivatives is None
281+
if anat_only:
282+
self._require_bold = False
283+
self._require_pet = False
284+
269285
super().__init__(*args, **kwargs)
270-
if anat_only is not None:
271-
self._require_funcs = not anat_only
272-
self._require_t1w = require_t1w and anat_derivatives is None
273286

274287
def _run_interface(self, runtime):
275288
bids_dict = self.inputs.subject_data
276289

277290
self._results['out_dict'] = bids_dict
278291
self._results.update(bids_dict)
279292

280-
if self._require_t1w and not bids_dict['t1w']:
281-
raise FileNotFoundError(
282-
f'No T1w images found for subject sub-{self.inputs.subject_id}'
283-
)
284-
285-
if self._require_funcs and not bids_dict['bold']:
286-
raise FileNotFoundError(
287-
f'No functional images found for subject sub-{self.inputs.subject_id}'
288-
)
289-
290-
for imtype in ['bold', 't2w', 'flair', 'fmap', 'sbref', 'roi', 'pet', 'asl']:
293+
for imtype in self._image_types:
291294
if not bids_dict[imtype]:
292-
LOGGER.info('No "%s" images found for sub-%s', imtype, self.inputs.subject_id)
295+
msg = f'No "{imtype}" images found for sub-{self.inputs.subject_id}'
296+
if getattr(self, f'_require_{imtype}', False): # only raise if image is required
297+
raise FileNotFoundError(msg)
298+
LOGGER.info(msg)
293299

294300
return runtime
295301

niworkflows/interfaces/tests/test_bids.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -798,11 +798,61 @@ def test_fsdir_min_version(tmp_path, min_version):
798798
def test_BIDSDataGrabber():
799799
x = bintfs.BIDSDataGrabber(anat_only=True)
800800
assert x._require_t1w is True
801-
assert x._require_funcs is False
801+
assert x._require_bold is False
802802

803803
x = bintfs.BIDSDataGrabber(anat_only=False, require_t1w=False)
804804
assert x._require_t1w is False
805-
assert x._require_funcs is True
805+
assert x._require_bold is True
806806

807807
x = bintfs.BIDSDataGrabber(anat_derivatives='derivatives')
808808
assert x._require_t1w is False
809+
810+
811+
def test_require_bold_pet_behavior():
812+
import pytest
813+
814+
from niworkflows.interfaces.bids import BIDSDataGrabber
815+
816+
subject_data_pet = {
817+
't1w': ['t1.nii'],
818+
'bold': [],
819+
'pet': ['pet.nii'],
820+
't2w': [],
821+
'flair': [],
822+
'fmap': [],
823+
'sbref': [],
824+
'roi': [],
825+
'asl': [],
826+
'dwi': [],
827+
}
828+
829+
subject_data_bold = {
830+
't1w': ['t1.nii'],
831+
'bold': ['bold.nii'],
832+
'pet': [],
833+
't2w': [],
834+
'flair': [],
835+
'fmap': [],
836+
'sbref': [],
837+
'roi': [],
838+
'asl': [],
839+
'dwi': [],
840+
}
841+
842+
# PET present, functional not required
843+
grabber_pet = BIDSDataGrabber(
844+
subject_data=subject_data_pet, subject_id='01', require_pet=True, require_bold=False
845+
)
846+
assert grabber_pet._require_bold is False
847+
assert grabber_pet._require_pet is True
848+
grabber_pet.run() # Should succeed without bold data
849+
850+
# PET absent, functional required by default
851+
grabber_func = BIDSDataGrabber(subject_data=subject_data_bold, subject_id='01')
852+
assert grabber_func._require_bold is True
853+
assert grabber_func.run().outputs.bold == 'bold.nii'
854+
855+
# Fail when bold is required but missing
856+
grabber_fail = BIDSDataGrabber(subject_data=subject_data_pet, subject_id='01')
857+
with pytest.raises(FileNotFoundError, match='No "bold" images found'):
858+
grabber_fail.run()

niworkflows/utils/bids.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@
3434
from packaging.version import Version
3535

3636
DEFAULT_BIDS_QUERIES = {
37-
'bold': {'datatype': 'func', 'suffix': 'bold', 'part': ['mag', None]},
37+
'bold': {
38+
'datatype': 'func',
39+
'suffix': 'bold',
40+
'part': ['mag', None],
41+
},
3842
'dwi': {'suffix': 'dwi'},
3943
'flair': {'datatype': 'anat', 'suffix': 'FLAIR', 'part': ['mag', None]},
4044
'fmap': {'datatype': 'fmap'},
@@ -272,7 +276,7 @@ def collect_data(
272276
del layout_get_kwargs[entity]
273277

274278
if task:
275-
queries['bold']['task'] = task
279+
queries['bold']['task'] = queries['pet']['task'] = task
276280

277281
if echo:
278282
queries['bold']['echo'] = echo

0 commit comments

Comments
 (0)