diff --git a/.circleci/config.yml b/.circleci/config.yml index e47c6baf7..70fbeea7c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -779,7 +779,7 @@ jobs: --config $PWD/nipype.cfg -w /tmp/${DATASET}/work \ /tmp/data/${DATASET} /tmp/${DATASET}/derivatives participant \ ${FASTRACK_ARG} \ - --fs-no-reconall --t2s-coreg --use-syn-sdc \ + --fs-no-reconall --use-syn-sdc \ --dummy-scans 1 --sloppy --write-graph \ --output-spaces MNI152NLin2009cAsym \ --mem_mb 4096 --nthreads 2 -vv diff --git a/docs/workflows.rst b/docs/workflows.rst index c51d80a63..6e65d8ad0 100644 --- a/docs/workflows.rst +++ b/docs/workflows.rst @@ -576,8 +576,5 @@ T2* Driven Coregistration If multi-echo :abbr:`BOLD (blood-oxygen level-dependent)` data is supplied, this workflow uses the `tedana`_ `T2* workflow`_ to generate an adaptive T2* map and optimally weighted combination of all supplied single echo time series. -This optimaly combined time series is then carried forward for all subsequent +This optimally combined time series is then carried forward for all subsequent preprocessing steps. -Optionally, if the ``--t2s-coreg`` flag is supplied, the T2* map is then used -in place of the :ref:`BOLD reference image ` to -:ref:`register the BOLD series to the T1w image ` of the same subject. diff --git a/fmriprep/cli/parser.py b/fmriprep/cli/parser.py index 307b79b42..dbf9e9003 100644 --- a/fmriprep/cli/parser.py +++ b/fmriprep/cli/parser.py @@ -142,12 +142,6 @@ def _bids_filter(value): g_conf.add_argument( '--longitudinal', action='store_true', help='treat dataset as longitudinal - may increase runtime') - g_conf.add_argument( - '--t2s-coreg', action='store_true', - help='If provided with multi-echo BOLD dataset, create T2*-map and perform ' - 'T2*-driven coregistration. When multi-echo data is provided and this ' - 'option is not enabled, standard EPI-T1 coregistration is performed ' - 'using the middle echo.') g_conf.add_argument( '--output-spaces', nargs='*', action=OutputReferencesAction, help="""\ diff --git a/fmriprep/config.py b/fmriprep/config.py index 02eeff140..8ea7c3b8a 100644 --- a/fmriprep/config.py +++ b/fmriprep/config.py @@ -452,9 +452,6 @@ class workflow(_Config): spaces = None """Keeps the :py:class:`~niworkflows.utils.spaces.SpatialReferences` instance keeping standard and nonstandard spaces.""" - t2s_coreg = None - """Co-register echos before generating the T2\\* reference of - :abbr:`ME-EPI (multi-echo echo-planar imaging)`.""" use_aroma = None """Run ICA-:abbr:`AROMA (automatic removal of motion artifacts)`.""" use_bbr = None diff --git a/fmriprep/workflows/bold/base.py b/fmriprep/workflows/bold/base.py index fed81c9d8..88496962e 100644 --- a/fmriprep/workflows/bold/base.py +++ b/fmriprep/workflows/bold/base.py @@ -209,17 +209,6 @@ def init_func_preproc_wf(bold_file): 'slicetiming' not in config.workflow.ignore and (_get_series_len(ref_file) > 4 or "TooShort")) - # Check if MEEPI for T2* coregistration target - if config.workflow.t2s_coreg and not multiecho: - config.loggers.workflow.warning( - "No multiecho BOLD images found for T2* coregistration. " - "Using standard EPI-T1 coregistration.") - config.workflow.t2s_coreg = False - - # By default, force-bbr for t2s_coreg unless user specifies otherwise - if config.workflow.t2s_coreg and config.workflow.use_bbr is None: - config.workflow.use_bbr = True - # Build workflow workflow = Workflow(name=wf_name) workflow.__postdesc__ = """\ @@ -407,7 +396,6 @@ def init_func_preproc_wf(bold_file): bold_t2s_wf = init_bold_t2s_wf(echo_times=tes, mem_gb=mem_gb['resampled'], omp_nthreads=omp_nthreads, - t2s_coreg=config.workflow.t2s_coreg, name='bold_t2smap_wf') workflow.connect([ @@ -464,10 +452,14 @@ def init_func_preproc_wf(bold_file): ('outputnode.ref_image_brain', 'inputnode.epi_brain'), ('outputnode.bold_mask', 'inputnode.epi_mask')]), (bold_sdc_wf, bold_t1_trans_wf, [ - ('outputnode.out_warp', 'inputnode.fieldwarp')]), + ('outputnode.out_warp', 'inputnode.fieldwarp'), + ('outputnode.epi_mask', 'inputnode.ref_bold_mask'), + ('outputnode.epi_brain', 'inputnode.ref_bold_brain')]), (bold_sdc_wf, bold_bold_trans_wf, [ ('outputnode.out_warp', 'inputnode.fieldwarp'), ('outputnode.epi_mask', 'inputnode.bold_mask')]), + (bold_sdc_wf, bold_reg_wf, [ + ('outputnode.epi_brain', 'inputnode.ref_bold_brain')]), (bold_sdc_wf, summary, [('outputnode.method', 'distortion_correction')]), # Connect bold_confounds_wf (inputnode, bold_confounds_wf, [('t1w_tpms', 'inputnode.t1w_tpms'), @@ -479,6 +471,9 @@ def init_func_preproc_wf(bold_file): ('outputnode.itk_t1_to_bold', 'inputnode.t1_bold_xform')]), (bold_reference_wf, bold_confounds_wf, [ ('outputnode.skip_vols', 'inputnode.skip_vols')]), + (bold_bold_trans_wf, bold_confounds_wf, [ + ('outputnode.bold_mask', 'inputnode.bold_mask'), + ]), (bold_confounds_wf, outputnode, [ ('outputnode.confounds_file', 'confounds'), ]), @@ -494,32 +489,13 @@ def init_func_preproc_wf(bold_file): (outputnode, summary, [('confounds', 'confounds_file')]), ]) - if not config.workflow.t2s_coreg: - workflow.connect([ - (bold_sdc_wf, bold_reg_wf, [ - ('outputnode.epi_brain', 'inputnode.ref_bold_brain')]), - (bold_sdc_wf, bold_t1_trans_wf, [ - ('outputnode.epi_brain', 'inputnode.ref_bold_brain'), - ('outputnode.epi_mask', 'inputnode.ref_bold_mask')]), - ]) - else: - workflow.connect([ - # For t2s_coreg, replace EPI-to-T1w registration inputs - (bold_t2s_wf, bold_reg_wf, [ - ('outputnode.bold_ref_brain', 'inputnode.ref_bold_brain')]), - (bold_t2s_wf, bold_t1_trans_wf, [ - ('outputnode.bold_ref_brain', 'inputnode.ref_bold_brain'), - ('outputnode.bold_mask', 'inputnode.ref_bold_mask')]), - ]) - # for standard EPI data, pass along correct file if not multiecho: workflow.connect([ (inputnode, func_derivatives_wf, [ ('bold_file', 'inputnode.source_file')]), (bold_bold_trans_wf, bold_confounds_wf, [ - ('outputnode.bold', 'inputnode.bold'), - ('outputnode.bold_mask', 'inputnode.bold_mask')]), + ('outputnode.bold', 'inputnode.bold')]), (bold_split, bold_t1_trans_wf, [ ('out_files', 'inputnode.bold_split')]), ]) @@ -531,8 +507,7 @@ def init_func_preproc_wf(bold_file): (bold_bold_trans_wf, skullstrip_bold_wf, [ ('outputnode.bold', 'inputnode.in_file')]), (bold_t2s_wf, bold_confounds_wf, [ - ('outputnode.bold', 'inputnode.bold'), - ('outputnode.bold_mask', 'inputnode.bold_mask')]), + ('outputnode.bold', 'inputnode.bold')]), (bold_t2s_wf, bold_t1_trans_wf, [ ('outputnode.bold', 'inputnode.bold_split')]), ]) @@ -607,7 +582,7 @@ def init_func_preproc_wf(bold_file): ('outputnode.itk_bold_to_t1', 'transforms')]), (bold_t1_trans_wf, boldmask_to_t1w, [ ('outputnode.bold_mask_t1', 'reference_image')]), - (bold_bold_trans_wf if not multiecho else bold_t2s_wf, boldmask_to_t1w, [ + (bold_bold_trans_wf, boldmask_to_t1w, [ ('outputnode.bold_mask', 'input_image')]), (boldmask_to_t1w, outputnode, [ ('output_image', 'bold_mask_t1')]), @@ -645,7 +620,7 @@ def init_func_preproc_wf(bold_file): ('outputnode.xforms', 'inputnode.hmc_xforms')]), (bold_reg_wf, bold_std_trans_wf, [ ('outputnode.itk_bold_to_t1', 'inputnode.itk_bold_to_t1')]), - (bold_bold_trans_wf if not multiecho else bold_t2s_wf, bold_std_trans_wf, [ + (bold_bold_trans_wf, bold_std_trans_wf, [ ('outputnode.bold_mask', 'inputnode.bold_mask')]), (bold_sdc_wf, bold_std_trans_wf, [ ('outputnode.out_warp', 'inputnode.fieldwarp')]), @@ -817,7 +792,8 @@ def init_func_preproc_wf(bold_file): (carpetplot_select_std, carpetplot_wf, [ ('std2anat_xfm', 'inputnode.std2anat_xfm')]), (bold_bold_trans_wf if not multiecho else bold_t2s_wf, carpetplot_wf, [ - ('outputnode.bold', 'inputnode.bold'), + ('outputnode.bold', 'inputnode.bold')]), + (bold_bold_trans_wf, carpetplot_wf, [ ('outputnode.bold_mask', 'inputnode.bold_mask')]), (bold_reg_wf, carpetplot_wf, [ ('outputnode.itk_t1_to_bold', 'inputnode.t1_bold_xform')]), diff --git a/fmriprep/workflows/bold/t2s.py b/fmriprep/workflows/bold/t2s.py index 1cac39b12..643a6acd6 100644 --- a/fmriprep/workflows/bold/t2s.py +++ b/fmriprep/workflows/bold/t2s.py @@ -19,13 +19,12 @@ # pylint: disable=R0914 def init_bold_t2s_wf(echo_times, mem_gb, omp_nthreads, - t2s_coreg=False, name='bold_t2s_wf'): + name='bold_t2s_wf'): """ Combine multiple echos of :abbr:`ME-EPI (multi-echo echo-planar imaging)`. This workflow wraps the `tedana`_ `T2* workflow`_ to optimally - combine multiple echos and derive a T2* map for optional use as a - coregistration target. + combine multiple echos and derive a T2* map. The following steps are performed: #. :abbr:`HMC (head motion correction)` on individual echo files. @@ -43,8 +42,6 @@ def init_bold_t2s_wf(echo_times, mem_gb, omp_nthreads, Size of BOLD file in GB omp_nthreads : :obj:`int` Maximum number of threads an individual process may use - t2s_coreg : :obj:`bool` - Use the calculated T2*-map for T2*-driven coregistration name : :obj:`str` Name of workflow (default: ``bold_t2s_wf``) @@ -57,14 +54,9 @@ def init_bold_t2s_wf(echo_times, mem_gb, omp_nthreads, ------- bold the optimally combined time series for all supplied echos - bold_mask - the binarized, skull-stripped adaptive T2* map - bold_ref_brain - the adaptive T2* map """ from niworkflows.engine.workflows import LiterateWorkflow as Workflow - from niworkflows.func.util import init_skullstrip_bold_wf workflow = Workflow(name=name) workflow.__desc__ = """\ @@ -74,26 +66,20 @@ def init_bold_t2s_wf(echo_times, mem_gb, omp_nthreads, used to fit the model. The calculated T2* map was then used to optimally combine preprocessed BOLD across echoes following the method described in [@posse_t2s]. -The optimally combined time series was carried forward as the *preprocessed BOLD*{}. -""".format('' if not t2s_coreg else ', and the T2* map was also retained as the BOLD reference') +The optimally combined time series was carried forward as the *preprocessed BOLD*. +""" inputnode = pe.Node(niu.IdentityInterface(fields=['bold_file']), name='inputnode') - outputnode = pe.Node(niu.IdentityInterface(fields=['bold', 'bold_mask', 'bold_ref_brain']), - name='outputnode') + outputnode = pe.Node(niu.IdentityInterface(fields=['bold']), name='outputnode') LOGGER.log(25, 'Generating T2* map and optimally combined ME-EPI time series.') t2smap_node = pe.Node(T2SMap(echo_times=echo_times), name='t2smap_node') - skullstrip_t2smap_wf = init_skullstrip_bold_wf(name='skullstrip_t2smap_wf') workflow.connect([ (inputnode, t2smap_node, [('bold_file', 'in_files')]), (t2smap_node, outputnode, [('optimal_comb', 'bold')]), - (t2smap_node, skullstrip_t2smap_wf, [('t2star_map', 'inputnode.in_file')]), - (skullstrip_t2smap_wf, outputnode, [ - ('outputnode.mask_file', 'bold_mask'), - ('outputnode.skull_stripped_file', 'bold_ref_brain')]), ]) return workflow