Skip to content

Commit 4282770

Browse files
authored
Merge pull request #1496 from oesteban/rf/niworkflows-pr-299
[MAINT] Update to keep up with nipreps/niworkflows#299
2 parents 177c6d2 + 9f507a2 commit 4282770

File tree

8 files changed

+63
-51
lines changed

8 files changed

+63
-51
lines changed

docs/workflows.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ is presented below:
1919
:simple_form: yes
2020

2121
from fmriprep.workflows.base import init_single_subject_wf
22+
from collections import namedtuple
23+
BIDSLayout = namedtuple('BIDSLayout', ['root'], defaults='.')
2224
wf = init_single_subject_wf(
25+
layout=BIDSLayout(),
2326
subject_id='test',
2427
name='single_subject_wf',
2528
task_id='',
@@ -30,7 +33,6 @@ is presented below:
3033
freesurfer=True,
3134
reportlets_dir='.',
3235
output_dir='.',
33-
bids_dir='.',
3436
skull_strip_template='OASIS30ANTs',
3537
skull_strip_fixed_seed=False,
3638
template='MNI152NLin2009cAsym',

fmriprep/__about__.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,20 +84,19 @@
8484
]
8585

8686
REQUIRES = [
87-
'grabbit==0.2.3',
8887
'indexed_gzip>=0.8.8',
8988
'nibabel>=2.2.1',
9089
'nilearn',
9190
'nipype>=1.1.6',
9291
'nitime',
93-
'niworkflows>=0.6.1,<0.7.0a0',
92+
'niworkflows>=0.7.0,<0.8.0a0',
9493
'numpy',
9594
'pandas',
9695
'psutil>=5.4',
97-
'pybids==0.6.5',
96+
'pybids>=0.7.0,<0.8.0a0',
9897
'pyyaml',
9998
'scikit-image',
100-
'smriprep>=0.0.4,<0.1.0a0',
99+
'smriprep>=0.0.5,<0.1.0a0',
101100
'statsmodels',
102101
'tedana>=0.0.5',
103102
'templateflow>=0.0.4',

fmriprep/cli/run.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,7 @@ def build_workflow(opts, retval):
552552
from subprocess import check_call, CalledProcessError, TimeoutExpired
553553
from pkg_resources import resource_filename as pkgrf
554554
from shutil import copyfile
555+
from bids import BIDSLayout
555556

556557
from nipype import logging, config as ncfg
557558
from niworkflows.utils.bids import collect_participants
@@ -606,8 +607,9 @@ def build_workflow(opts, retval):
606607

607608
# First check that bids_dir looks like a BIDS folder
608609
bids_dir = os.path.abspath(opts.bids_dir)
610+
layout = BIDSLayout(bids_dir, validate=False)
609611
subject_list = collect_participants(
610-
bids_dir, participant_label=opts.participant_label)
612+
layout, participant_label=opts.participant_label)
611613

612614
# Load base plugin_settings from file if --use-plugin
613615
if opts.use_plugin is not None:
@@ -715,6 +717,7 @@ def build_workflow(opts, retval):
715717
logger.warning('Option --debug is deprecated and has no effect')
716718

717719
retval['workflow'] = init_fmriprep_wf(
720+
layout=layout,
718721
subject_list=subject_list,
719722
task_id=opts.task_id,
720723
echo_idx=opts.echo_idx,
@@ -730,7 +733,6 @@ def build_workflow(opts, retval):
730733
skull_strip_fixed_seed=opts.skull_strip_fixed_seed,
731734
work_dir=work_dir,
732735
output_dir=output_dir,
733-
bids_dir=bids_dir,
734736
freesurfer=opts.run_reconall,
735737
output_spaces=output_spaces,
736738
template=opts.template,

fmriprep/workflows/base.py

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
from .bold import init_func_preproc_wf
3434

3535

36-
def init_fmriprep_wf(subject_list, task_id, echo_idx, run_uuid, work_dir, output_dir, bids_dir,
36+
def init_fmriprep_wf(layout, subject_list, task_id, echo_idx, run_uuid, work_dir, output_dir,
3737
ignore, debug, low_mem, anat_only, longitudinal, t2s_coreg,
3838
omp_nthreads, skull_strip_template, skull_strip_fixed_seed,
3939
freesurfer, output_spaces, template, medial_surface_nan, cifti_output, hires,
@@ -51,15 +51,17 @@ def init_fmriprep_wf(subject_list, task_id, echo_idx, run_uuid, work_dir, output
5151
:simple_form: yes
5252
5353
import os
54-
os.environ['FREESURFER_HOME'] = os.getcwd()
54+
from collections import namedtuple
55+
BIDSLayout = namedtuple('BIDSLayout', ['root'], defaults='.')
5556
from fmriprep.workflows.base import init_fmriprep_wf
56-
wf = init_fmriprep_wf(subject_list=['fmripreptest'],
57+
os.environ['FREESURFER_HOME'] = os.getcwd()
58+
wf = init_fmriprep_wf(layout=BIDSLayout(),
59+
subject_list=['fmripreptest'],
5760
task_id='',
5861
echo_idx=None,
5962
run_uuid='X',
6063
work_dir='.',
6164
output_dir='.',
62-
bids_dir='.',
6365
ignore=[],
6466
debug=False,
6567
low_mem=False,
@@ -90,6 +92,8 @@ def init_fmriprep_wf(subject_list, task_id, echo_idx, run_uuid, work_dir, output
9092
9193
Parameters
9294
95+
layout : BIDSLayout object
96+
BIDS dataset layout
9397
subject_list : list
9498
List of subject labels
9599
task_id : str or None
@@ -103,8 +107,6 @@ def init_fmriprep_wf(subject_list, task_id, echo_idx, run_uuid, work_dir, output
103107
Directory in which to store workflow execution state and temporary files
104108
output_dir : str
105109
Directory in which to save derivatives
106-
bids_dir : str
107-
Root directory of BIDS dataset
108110
ignore : list
109111
Preprocessing steps to skip (may include "slicetiming", "fieldmaps")
110112
debug : bool
@@ -182,13 +184,13 @@ def init_fmriprep_wf(subject_list, task_id, echo_idx, run_uuid, work_dir, output
182184
reportlets_dir = os.path.join(work_dir, 'reportlets')
183185
for subject_id in subject_list:
184186
single_subject_wf = init_single_subject_wf(
187+
layout=layout,
185188
subject_id=subject_id,
186189
task_id=task_id,
187190
echo_idx=echo_idx,
188191
name="single_subject_" + subject_id + "_wf",
189192
reportlets_dir=reportlets_dir,
190193
output_dir=output_dir,
191-
bids_dir=bids_dir,
192194
ignore=ignore,
193195
debug=debug,
194196
low_mem=low_mem,
@@ -230,8 +232,8 @@ def init_fmriprep_wf(subject_list, task_id, echo_idx, run_uuid, work_dir, output
230232
return fmriprep_wf
231233

232234

233-
def init_single_subject_wf(subject_id, task_id, echo_idx, name, reportlets_dir, output_dir,
234-
bids_dir, ignore, debug, low_mem, anat_only, longitudinal, t2s_coreg,
235+
def init_single_subject_wf(layout, subject_id, task_id, echo_idx, name, reportlets_dir,
236+
output_dir, ignore, debug, low_mem, anat_only, longitudinal, t2s_coreg,
235237
omp_nthreads, skull_strip_template, skull_strip_fixed_seed,
236238
freesurfer, output_spaces, template, medial_surface_nan,
237239
cifti_output, hires, use_bbr, bold2t1w_dof, fmap_bspline, fmap_demean,
@@ -252,13 +254,15 @@ def init_single_subject_wf(subject_id, task_id, echo_idx, name, reportlets_dir,
252254
:simple_form: yes
253255
254256
from fmriprep.workflows.base import init_single_subject_wf
255-
wf = init_single_subject_wf(subject_id='test',
257+
from collections import namedtuple
258+
BIDSLayout = namedtuple('BIDSLayout', ['root'], defaults='.')
259+
wf = init_single_subject_wf(layout=BIDSLayout(),
260+
subject_id='test',
256261
task_id='',
257262
echo_idx=None,
258263
name='single_subject_wf',
259264
reportlets_dir='.',
260265
output_dir='.',
261-
bids_dir='.',
262266
ignore=[],
263267
debug=False,
264268
low_mem=False,
@@ -288,6 +292,8 @@ def init_single_subject_wf(subject_id, task_id, echo_idx, name, reportlets_dir,
288292
289293
Parameters
290294
295+
layout : BIDSLayout object
296+
BIDS dataset layout
291297
subject_id : str
292298
List of subject labels
293299
task_id : str or None
@@ -321,8 +327,6 @@ def init_single_subject_wf(subject_id, task_id, echo_idx, name, reportlets_dir,
321327
Directory in which to save reportlets
322328
output_dir : str
323329
Directory in which to save derivatives
324-
bids_dir : str
325-
Root directory of BIDS dataset
326330
freesurfer : bool
327331
Enable FreeSurfer surface reconstruction (may increase runtime)
328332
output_spaces : list
@@ -377,9 +381,8 @@ def init_single_subject_wf(subject_id, task_id, echo_idx, name, reportlets_dir,
377381
't1w': ['/completely/made/up/path/sub-01_T1w.nii.gz'],
378382
'bold': ['/completely/made/up/path/sub-01_task-nback_bold.nii.gz']
379383
}
380-
layout = None
381384
else:
382-
subject_data, layout = collect_data(bids_dir, subject_id, task_id, echo_idx)
385+
subject_data = collect_data(layout, subject_id, task_id, echo_idx)[0]
383386

384387
# Make sure we always go through these two checks
385388
if not anat_only and subject_data['bold'] == []:
@@ -421,7 +424,8 @@ def init_single_subject_wf(subject_id, task_id, echo_idx, name, reportlets_dir,
421424
bidssrc = pe.Node(BIDSDataGrabber(subject_data=subject_data, anat_only=anat_only),
422425
name='bidssrc')
423426

424-
bids_info = pe.Node(BIDSInfo(), name='bids_info', run_without_submitting=True)
427+
bids_info = pe.Node(BIDSInfo(
428+
bids_dir=layout.root, bids_validate=False), name='bids_info')
425429

426430
summary = pe.Node(SubjectSummary(output_spaces=output_spaces, template=template),
427431
name='summary', run_without_submitting=True)
@@ -464,12 +468,12 @@ def init_single_subject_wf(subject_id, task_id, echo_idx, name, reportlets_dir,
464468
(bidssrc, summary, [('t1w', 't1w'),
465469
('t2w', 't2w'),
466470
('bold', 'bold')]),
467-
(bids_info, summary, [('subject_id', 'subject_id')]),
471+
(bids_info, summary, [('subject', 'subject_id')]),
472+
(bids_info, anat_preproc_wf, [(('subject', _prefix), 'inputnode.subject_id')]),
468473
(bidssrc, anat_preproc_wf, [('t1w', 'inputnode.t1w'),
469474
('t2w', 'inputnode.t2w'),
470475
('roi', 'inputnode.roi'),
471476
('flair', 'inputnode.flair')]),
472-
(summary, anat_preproc_wf, [('subject_id', 'inputnode.subject_id')]),
473477
(bidssrc, ds_report_summary, [(('t1w', fix_multi_T1w_source_name), 'source_file')]),
474478
(summary, ds_report_summary, [('out_report', 'in_file')]),
475479
(bidssrc, ds_report_about, [(('t1w', fix_multi_T1w_source_name), 'source_file')]),
@@ -532,3 +536,9 @@ def init_single_subject_wf(subject_id, task_id, echo_idx, name, reportlets_dir,
532536
])
533537

534538
return workflow
539+
540+
541+
def _prefix(subid):
542+
if subid.startswith('sub-'):
543+
return subid
544+
return '-'.join(('sub', subid))

fmriprep/workflows/bold/base.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -246,15 +246,15 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
246246

247247
sbref_file = None
248248
# For doc building purposes
249-
if layout is None or bold_file == 'bold_preprocesing':
249+
if not hasattr(layout, 'parse_file_entities'):
250250
LOGGER.log(25, 'No valid layout: building empty workflow.')
251251
metadata = {
252252
'RepetitionTime': 2.0,
253253
'SliceTiming': [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9],
254254
'PhaseEncodingDirection': 'j',
255255
}
256256
fmaps = [{
257-
'type': 'phasediff',
257+
'suffix': 'phasediff',
258258
'phasediff': 'sub-03/ses-2/fmap/sub-03_ses-2_run-1_phasediff.nii.gz',
259259
'magnitude1': 'sub-03/ses-2/fmap/sub-03_ses-2_run-1_magnitude1.nii.gz',
260260
'magnitude2': 'sub-03/ses-2/fmap/sub-03_ses-2_run-1_magnitude2.nii.gz',
@@ -264,16 +264,16 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
264264
else:
265265
# Find associated sbref, if possible
266266
entities = layout.parse_file_entities(ref_file)
267-
entities['type'] = 'sbref'
268-
files = layout.get(**entities, extensions=['nii', 'nii.gz'])
267+
entities['suffix'] = 'sbref'
268+
files = layout.get(return_type='file', extensions=['nii', 'nii.gz'], **entities)
269269
refbase = os.path.basename(ref_file)
270270
if 'sbref' in ignore:
271271
LOGGER.info("Single-band reference files ignored.")
272272
elif files and multiecho:
273273
LOGGER.warning("Single-band reference found, but not supported in "
274274
"multi-echo workflows at this time. Ignoring.")
275275
elif files:
276-
sbref_file = files[0].filename
276+
sbref_file = files[0]
277277
sbbase = os.path.basename(sbref_file)
278278
if len(files) > 1:
279279
LOGGER.warning(
@@ -291,11 +291,11 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
291291
if 'fieldmaps' not in ignore:
292292
fmaps = layout.get_fieldmap(ref_file, return_list=True)
293293
for fmap in fmaps:
294-
fmap['metadata'] = layout.get_metadata(fmap[fmap['type']])
294+
fmap['metadata'] = layout.get_metadata(fmap[fmap['suffix']])
295295

296296
# Run SyN if forced or in the absence of fieldmap correction
297297
if force_syn or (use_syn and not fmaps):
298-
fmaps.append({'type': 'syn'})
298+
fmaps.append({'suffix': 'syn'})
299299

300300
# Short circuits: (True and True and (False or 'TooShort')) == 'TooShort'
301301
run_stc = ("SliceTiming" in metadata and
@@ -476,14 +476,14 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
476476
if not fmaps:
477477
LOGGER.warning('SDC: no fieldmaps found or they were ignored (%s).',
478478
ref_file)
479-
elif fmaps[0]['type'] == 'syn':
479+
elif fmaps[0]['suffix'] == 'syn':
480480
LOGGER.warning(
481481
'SDC: no fieldmaps found or they were ignored. '
482482
'Using EXPERIMENTAL "fieldmap-less SyN" correction '
483483
'for dataset %s.', ref_file)
484484
else:
485485
LOGGER.log(25, 'SDC: fieldmap estimation of type "%s" intended for %s found.',
486-
fmaps[0]['type'], ref_file)
486+
fmaps[0]['suffix'], ref_file)
487487

488488
# MULTI-ECHO EPI DATA #############################################
489489
if multiecho:
@@ -613,7 +613,7 @@ def init_func_preproc_wf(bold_file, ignore, freesurfer,
613613

614614
if fmaps:
615615
from ..fieldmap.unwarp import init_fmap_unwarp_report_wf
616-
sdc_type = fmaps[0]['type']
616+
sdc_type = fmaps[0]['suffix']
617617

618618
# Report on BOLD correction
619619
fmap_unwarp_report_wf = init_fmap_unwarp_report_wf(

fmriprep/workflows/fieldmap/base.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
7979
from fmriprep.workflows.fieldmap import init_sdc_wf
8080
wf = init_sdc_wf(
8181
fmaps=[{
82-
'type': 'phasediff',
82+
'suffix': 'phasediff',
8383
'phasediff': 'sub-03/ses-2/fmap/sub-03_ses-2_run-1_phasediff.nii.gz',
8484
'magnitude1': 'sub-03/ses-2/fmap/sub-03_ses-2_run-1_magnitude1.nii.gz',
8585
'magnitude2': 'sub-03/ses-2/fmap/sub-03_ses-2_run-1_magnitude2.nii.gz',
@@ -140,7 +140,7 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
140140
"""
141141

142142
# TODO: To be removed (filter out unsupported fieldmaps):
143-
fmaps = [fmap for fmap in fmaps if fmap['type'] in FMAP_PRIORITY]
143+
fmaps = [fmap for fmap in fmaps if fmap['suffix'] in FMAP_PRIORITY]
144144

145145
workflow = Workflow(name='sdc_wf' if fmaps else 'sdc_bypass_wf')
146146
inputnode = pe.Node(niu.IdentityInterface(
@@ -170,15 +170,15 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
170170
"""
171171

172172
# In case there are multiple fieldmaps prefer EPI
173-
fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap['type']])
173+
fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap['suffix']])
174174
fmap = fmaps[0]
175175

176176
# PEPOLAR path
177-
if fmap['type'] == 'epi':
177+
if fmap['suffix'] == 'epi':
178178
outputnode.inputs.method = 'PEB/PEPOLAR (phase-encoding based / PE-POLARity)'
179179
# Get EPI polarities and their metadata
180180
epi_fmaps = [(fmap_['epi'], fmap_['metadata']["PhaseEncodingDirection"])
181-
for fmap_ in fmaps if fmap_['type'] == 'epi']
181+
for fmap_ in fmaps if fmap_['suffix'] == 'epi']
182182
sdc_unwarp_wf = init_pepolar_unwarp_wf(
183183
bold_meta=bold_meta,
184184
epi_fmaps=epi_fmaps,
@@ -193,11 +193,11 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
193193
])
194194

195195
# FIELDMAP path
196-
if fmap['type'] in ['fieldmap', 'phasediff']:
197-
outputnode.inputs.method = 'FMB (%s-based)' % fmap['type']
196+
if fmap['suffix'] in ['fieldmap', 'phasediff']:
197+
outputnode.inputs.method = 'FMB (%s-based)' % fmap['suffix']
198198
# Import specific workflows here, so we don't break everything with one
199199
# unused workflow.
200-
if fmap['type'] == 'fieldmap':
200+
if fmap['suffix'] == 'fieldmap':
201201
from .fmap import init_fmap_wf
202202
fmap_estimator_wf = init_fmap_wf(
203203
omp_nthreads=omp_nthreads,
@@ -206,7 +206,7 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
206206
fmap_estimator_wf.inputs.inputnode.fieldmap = fmap['fieldmap']
207207
fmap_estimator_wf.inputs.inputnode.magnitude = fmap['magnitude']
208208

209-
if fmap['type'] == 'phasediff':
209+
if fmap['suffix'] == 'phasediff':
210210
from .phdiff import init_phdiff_wf
211211
fmap_estimator_wf = init_phdiff_wf(omp_nthreads=omp_nthreads)
212212
# set inputs
@@ -235,7 +235,7 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
235235
])
236236

237237
# FIELDMAP-less path
238-
if any(fm['type'] == 'syn' for fm in fmaps):
238+
if any(fm['suffix'] == 'syn' for fm in fmaps):
239239
syn_sdc_wf = init_syn_sdc_wf(
240240
bold_pe=bold_meta.get('PhaseEncodingDirection', None),
241241
omp_nthreads=omp_nthreads)
@@ -250,7 +250,7 @@ def init_sdc_wf(fmaps, bold_meta, omp_nthreads=1,
250250
])
251251

252252
# XXX Eliminate branch when forcing isn't an option
253-
if fmap['type'] == 'syn': # No fieldmaps, but --use-syn
253+
if fmap['suffix'] == 'syn': # No fieldmaps, but --use-syn
254254
outputnode.inputs.method = 'FLB ("fieldmap-less", SyN-based)'
255255
sdc_unwarp_wf = syn_sdc_wf
256256
else: # --force-syn was called when other fieldmap was present

fmriprep/workflows/fieldmap/phdiff.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def _pick1st(inlist):
7373
return inlist[0]
7474

7575
# Read phasediff echo times
76-
meta = pe.Node(ReadSidecarJSON(), name='meta', mem_gb=0.01, run_without_submitting=True)
76+
meta = pe.Node(ReadSidecarJSON(bids_validate=False), name='meta', mem_gb=0.01)
7777

7878
# Merge input magnitude images
7979
magmrg = pe.Node(IntraModalMerge(), name='magmrg')

0 commit comments

Comments
 (0)