Skip to content

Commit 4b16afb

Browse files
committed
feat: Add --force flag, deprecate --force[-no]-bbr
1 parent 2106034 commit 4b16afb

File tree

4 files changed

+41
-22
lines changed

4 files changed

+41
-22
lines changed

fmriprep/cli/parser.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ def _build_parser(**kwargs):
4848
'aroma_err_on_warn': (None, '24.0.0'),
4949
'bold2t1w_init': ('--bold2anat-init', '24.2.0'),
5050
'bold2t1w_dof': ('--bold2anat-dof', '24.2.0'),
51+
'force_bbr': ('--force bbr', '26.0.0'),
52+
'force_no_bbr': ('--force no-bbr', '26.0.0'),
5153
}
5254

5355
class DeprecatedAction(Action):
@@ -338,6 +340,16 @@ def _slice_time_ref(value, parser):
338340
help='Ignore selected aspects of the input dataset to disable corresponding '
339341
'parts of the workflow (a space delimited list)',
340342
)
343+
g_conf.add_argument(
344+
'--force',
345+
required=False,
346+
action='store',
347+
nargs='+',
348+
default=[],
349+
choices=['bbr', 'no-bbr'],
350+
help='Force selected processing choices, overriding automatic selections '
351+
'(a space delimited list)',
352+
)
341353
g_conf.add_argument(
342354
'--output-spaces',
343355
nargs='*',
@@ -392,17 +404,13 @@ def _slice_time_ref(value, parser):
392404
)
393405
g_conf.add_argument(
394406
'--force-bbr',
395-
action='store_true',
396-
dest='use_bbr',
397-
default=None,
398-
help='Always use boundary-based registration (no goodness-of-fit checks)',
407+
action=DeprecatedAction,
408+
help='Deprecated - use `--force bbr` instead.',
399409
)
400410
g_conf.add_argument(
401411
'--force-no-bbr',
402-
action='store_false',
403-
dest='use_bbr',
404-
default=None,
405-
help='Do not use boundary-based registration (no goodness-of-fit checks)',
412+
action=DeprecatedAction,
413+
help='Deprecated - use `--force no-bbr` instead.',
406414
)
407415
g_conf.add_argument(
408416
'--slice-time-ref',

fmriprep/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,8 @@ class workflow(_Config):
581581
"""Adjust pipeline to reuse base template of existing longitudinal freesurfer"""
582582
ignore = None
583583
"""Ignore particular steps for *fMRIPrep*."""
584+
force = None
585+
"""Force particular steps for *fMRIPrep*."""
584586
level = None
585587
"""Level of preprocessing to complete. One of ['minimal', 'resampling', 'full']."""
586588
longitudinal = False

fmriprep/workflows/bold/fit.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,11 +613,18 @@ def init_bold_fit_wf(
613613
]) # fmt:skip
614614

615615
if not boldref2anat_xform:
616+
use_bbr = (
617+
True
618+
if 'bbr' in config.workflow.force
619+
else False
620+
if 'no-bbr' in config.workflow.force
621+
else None
622+
)
616623
# calculate BOLD registration to T1w
617624
bold_reg_wf = init_bold_reg_wf(
618625
bold2anat_dof=config.workflow.bold2anat_dof,
619626
bold2anat_init=config.workflow.bold2anat_init,
620-
use_bbr=config.workflow.use_bbr,
627+
use_bbr=use_bbr,
621628
freesurfer=config.workflow.run_reconall,
622629
omp_nthreads=omp_nthreads,
623630
mem_gb=mem_gb['resampled'],

fmriprep/workflows/tests/test_base.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ def bids_root(tmp_path_factory):
106106

107107
def _make_params(
108108
bold2anat_init: str = 'auto',
109-
use_bbr: bool | None = None,
110109
dummy_scans: int | None = None,
111110
me_output_echos: bool = False,
112111
medial_surface_nan: bool = False,
@@ -118,15 +117,17 @@ def _make_params(
118117
force_syn: bool = False,
119118
freesurfer: bool = True,
120119
ignore: list[str] = None,
120+
force: list[str] = None,
121121
bids_filters: dict = None,
122122
):
123123
if ignore is None:
124124
ignore = []
125+
if force is None:
126+
force = []
125127
if bids_filters is None:
126128
bids_filters = {}
127129
return (
128130
bold2anat_init,
129-
use_bbr,
130131
dummy_scans,
131132
me_output_echos,
132133
medial_surface_nan,
@@ -138,6 +139,7 @@ def _make_params(
138139
force_syn,
139140
freesurfer,
140141
ignore,
142+
force,
141143
bids_filters,
142144
)
143145

@@ -147,7 +149,6 @@ def _make_params(
147149
@pytest.mark.parametrize(
148150
(
149151
'bold2anat_init',
150-
'use_bbr',
151152
'dummy_scans',
152153
'me_output_echos',
153154
'medial_surface_nan',
@@ -159,18 +160,19 @@ def _make_params(
159160
'force_syn',
160161
'freesurfer',
161162
'ignore',
163+
'force',
162164
'bids_filters',
163165
),
164166
[
165167
_make_params(),
166168
_make_params(bold2anat_init='t1w'),
167169
_make_params(bold2anat_init='t2w'),
168170
_make_params(bold2anat_init='header'),
169-
_make_params(use_bbr=True),
170-
_make_params(use_bbr=False),
171-
_make_params(bold2anat_init='header', use_bbr=True),
171+
_make_params(force=['bbr']),
172+
_make_params(force=['no-bbr']),
173+
_make_params(bold2anat_init='header', force=['bbr']),
172174
# Currently disabled
173-
# _make_params(bold2anat_init="header", use_bbr=False),
175+
# _make_params(bold2anat_init="header", force=['no-bbr']),
174176
_make_params(dummy_scans=2),
175177
_make_params(me_output_echos=True),
176178
_make_params(medial_surface_nan=True),
@@ -182,12 +184,12 @@ def _make_params(
182184
_make_params(skull_strip_t1w='skip'),
183185
_make_params(use_syn_sdc='warn', force_syn=True, ignore=['fieldmaps']),
184186
_make_params(freesurfer=False),
185-
_make_params(freesurfer=False, use_bbr=True),
186-
_make_params(freesurfer=False, use_bbr=False),
187+
_make_params(freesurfer=False, force=['bbr']),
188+
_make_params(freesurfer=False, force=['no-bbr']),
187189
# Currently unsupported:
188190
# _make_params(freesurfer=False, bold2anat_init="header"),
189-
# _make_params(freesurfer=False, bold2anat_init="header", use_bbr=True),
190-
# _make_params(freesurfer=False, bold2anat_init="header", use_bbr=False),
191+
# _make_params(freesurfer=False, bold2anat_init="header", force=['bbr']),
192+
# _make_params(freesurfer=False, bold2anat_init="header", force=['no-bbr']),
191193
# Regression test for gh-3154:
192194
_make_params(bids_filters={'sbref': {'suffix': 'sbref'}}),
193195
],
@@ -198,7 +200,6 @@ def test_init_fmriprep_wf(
198200
level: str,
199201
anat_only: bool,
200202
bold2anat_init: str,
201-
use_bbr: bool | None,
202203
dummy_scans: int | None,
203204
me_output_echos: bool,
204205
medial_surface_nan: bool,
@@ -210,13 +211,13 @@ def test_init_fmriprep_wf(
210211
force_syn: bool,
211212
freesurfer: bool,
212213
ignore: list[str],
214+
force: list[str],
213215
bids_filters: dict,
214216
):
215217
with mock_config(bids_dir=bids_root):
216218
config.workflow.level = level
217219
config.workflow.anat_only = anat_only
218220
config.workflow.bold2anat_init = bold2anat_init
219-
config.workflow.use_bbr = use_bbr
220221
config.workflow.dummy_scans = dummy_scans
221222
config.execution.me_output_echos = me_output_echos
222223
config.workflow.medial_surface_nan = medial_surface_nan
@@ -226,6 +227,7 @@ def test_init_fmriprep_wf(
226227
config.workflow.cifti_output = cifti_output
227228
config.workflow.run_reconall = freesurfer
228229
config.workflow.ignore = ignore
230+
config.workflow.force = force
229231
with patch.dict('fmriprep.config.execution.bids_filters', bids_filters):
230232
wf = init_fmriprep_wf()
231233

0 commit comments

Comments
 (0)