-
Notifications
You must be signed in to change notification settings - Fork 308
REF: Split final boldref generation from BOLD-BOLD resampling, eliminate extra per-echo computation #2181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
REF: Split final boldref generation from BOLD-BOLD resampling, eliminate extra per-echo computation #2181
Changes from 16 commits
abee610
cd1925d
559e11c
a5e387d
0b8a388
d3d3dab
5d8fe48
211c298
309a613
80aa3b6
0f8936a
9e5a689
71226b9
9d530ea
3703963
3e9d2cb
7415cbb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -125,7 +125,7 @@ def init_func_preproc_wf(bold_file): | |
| * :py:func:`~fmriprep.workflows.bold.t2s.init_bold_t2s_wf` | ||
| * :py:func:`~fmriprep.workflows.bold.registration.init_bold_t1_trans_wf` | ||
| * :py:func:`~fmriprep.workflows.bold.registration.init_bold_reg_wf` | ||
| * :py:func:`~fmriprep.workflows.bold.confounds.init_bold_confounds_wf` | ||
| * :py:func:`~fmriprep.workflows.bold.confounds.init_bold_confs_wf` | ||
| * :py:func:`~fmriprep.workflows.bold.confounds.init_ica_aroma_wf` | ||
| * :py:func:`~fmriprep.workflows.bold.resampling.init_bold_std_trans_wf` | ||
| * :py:func:`~fmriprep.workflows.bold.resampling.init_bold_preproc_trans_wf` | ||
|
|
@@ -307,13 +307,14 @@ def init_func_preproc_wf(bold_file): | |
| ]) | ||
|
|
||
| # Generate a tentative boldref | ||
| bold_reference_wf = init_bold_reference_wf( | ||
| initial_boldref_wf = init_bold_reference_wf( | ||
| name='initial_boldref_wf', | ||
| omp_nthreads=omp_nthreads, | ||
| bold_file=bold_file, | ||
| sbref_files=sbref_files, | ||
| multiecho=multiecho, | ||
| ) | ||
| bold_reference_wf.inputs.inputnode.dummy_scans = config.workflow.dummy_scans | ||
| initial_boldref_wf.inputs.inputnode.dummy_scans = config.workflow.dummy_scans | ||
|
|
||
| # Top-level BOLD splitter | ||
| bold_split = pe.Node(FSLSplit(dimension='t'), name='bold_split', | ||
|
|
@@ -365,17 +366,26 @@ def init_func_preproc_wf(bold_file): | |
| ) | ||
| bold_bold_trans_wf.inputs.inputnode.name_source = ref_file | ||
|
|
||
| # Generate a new BOLD reference | ||
| # This BOLD references *does not use* single-band reference images. | ||
| final_boldref_wf = init_bold_reference_wf( | ||
| name='final_boldref_wf', | ||
| omp_nthreads=omp_nthreads, | ||
| multiecho=multiecho, | ||
| ) | ||
| final_boldref_wf.__desc__ = None # Unset description to avoid second appearance | ||
|
|
||
| # SLICE-TIME CORRECTION (or bypass) ############################################# | ||
| if run_stc is True: # bool('TooShort') == True, so check True explicitly | ||
| bold_stc_wf = init_bold_stc_wf(name='bold_stc_wf', metadata=metadata) | ||
| workflow.connect([ | ||
| (bold_reference_wf, bold_stc_wf, [ | ||
| (initial_boldref_wf, bold_stc_wf, [ | ||
| ('outputnode.skip_vols', 'inputnode.skip_vols')]), | ||
| (bold_stc_wf, boldbuffer, [('outputnode.stc_file', 'bold_file')]), | ||
| ]) | ||
| if not multiecho: | ||
| workflow.connect([ | ||
| (bold_reference_wf, bold_stc_wf, [ | ||
| (initial_boldref_wf, bold_stc_wf, [ | ||
| ('outputnode.bold_file', 'inputnode.bold_file')])]) | ||
| else: # for meepi, iterate through stc_wf for all workflows | ||
| meepi_echos = boldbuffer.clone(name='meepi_echos') | ||
|
|
@@ -385,7 +395,7 @@ def init_func_preproc_wf(bold_file): | |
| elif not multiecho: # STC is too short or False | ||
| # bypass STC from original BOLD to the splitter through boldbuffer | ||
| workflow.connect([ | ||
| (bold_reference_wf, boldbuffer, [('outputnode.bold_file', 'bold_file')])]) | ||
| (initial_boldref_wf, boldbuffer, [('outputnode.bold_file', 'bold_file')])]) | ||
| else: | ||
| # for meepi, iterate over all meepi echos to boldbuffer | ||
| boldbuffer.iterables = ('bold_file', bold_file) | ||
|
|
@@ -404,10 +414,12 @@ def init_func_preproc_wf(bold_file): | |
|
|
||
| inputnode.inputs.bold_file = ref_file # Replace reference w first echo | ||
|
|
||
| join_echos = pe.JoinNode(niu.IdentityInterface(fields=['bold_files']), | ||
| joinsource=('meepi_echos' if run_stc is True else 'boldbuffer'), | ||
| joinfield=['bold_files'], | ||
| name='join_echos') | ||
| join_echos = pe.JoinNode( | ||
| niu.IdentityInterface(fields=['bold_files', 'skullstripped_bold_files']), | ||
| joinsource=('meepi_echos' if run_stc is True else 'boldbuffer'), | ||
| joinfield=['bold_files', 'skullstripped_bold_files'], | ||
| name='join_echos' | ||
| ) | ||
|
|
||
| # create optimal combination, adaptive T2* map | ||
| bold_t2s_wf = init_bold_t2s_wf(echo_times=tes, | ||
|
|
@@ -422,10 +434,10 @@ def init_func_preproc_wf(bold_file): | |
| # BOLD buffer has slice-time corrected if it was run, original otherwise | ||
| (boldbuffer, bold_split, [('bold_file', 'in_file')]), | ||
| # HMC | ||
| (bold_reference_wf, bold_hmc_wf, [ | ||
| (initial_boldref_wf, bold_hmc_wf, [ | ||
| ('outputnode.raw_ref_image', 'inputnode.raw_ref_image'), | ||
| ('outputnode.bold_file', 'inputnode.bold_file')]), | ||
| (bold_reference_wf, summary, [ | ||
| (initial_boldref_wf, summary, [ | ||
| ('outputnode.algo_dummy_scans', 'algo_dummy_scans')]), | ||
| # EPI-T1 registration workflow | ||
| (inputnode, bold_reg_wf, [ | ||
|
|
@@ -456,7 +468,7 @@ def init_func_preproc_wf(bold_file): | |
| # SDC (or pass-through workflow) | ||
| (t1w_brain, bold_sdc_wf, [ | ||
| ('out_file', 'inputnode.t1w_brain')]), | ||
| (bold_reference_wf, bold_sdc_wf, [ | ||
| (initial_boldref_wf, bold_sdc_wf, [ | ||
| ('outputnode.ref_image', 'inputnode.epi_file'), | ||
| ('outputnode.ref_image_brain', 'inputnode.epi_brain'), | ||
| ('outputnode.bold_mask', 'inputnode.epi_mask')]), | ||
|
|
@@ -477,11 +489,10 @@ def init_func_preproc_wf(bold_file): | |
| ('outputnode.rmsd_file', 'inputnode.rmsd_file')]), | ||
| (bold_reg_wf, bold_confounds_wf, [ | ||
| ('outputnode.itk_t1_to_bold', 'inputnode.t1_bold_xform')]), | ||
| (bold_reference_wf, bold_confounds_wf, [ | ||
| (initial_boldref_wf, bold_confounds_wf, [ | ||
| ('outputnode.skip_vols', 'inputnode.skip_vols')]), | ||
| (bold_bold_trans_wf, bold_confounds_wf, [ | ||
| ('outputnode.bold_mask', 'inputnode.bold_mask'), | ||
| ]), | ||
| (final_boldref_wf, bold_confounds_wf, [ | ||
| ('outputnode.bold_mask', 'inputnode.bold_mask')]), | ||
| (bold_confounds_wf, outputnode, [ | ||
tsalo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ('outputnode.confounds_file', 'confounds'), | ||
| ]), | ||
|
|
@@ -504,6 +515,8 @@ def init_func_preproc_wf(bold_file): | |
| ('bold_file', 'inputnode.source_file')]), | ||
| (bold_bold_trans_wf, bold_confounds_wf, [ | ||
| ('outputnode.bold', 'inputnode.bold')]), | ||
| (bold_bold_trans_wf, final_boldref_wf, [ | ||
| ('outputnode.bold', 'inputnode.bold_file')]), | ||
| (bold_split, bold_t1_trans_wf, [ | ||
| ('out_files', 'inputnode.bold_split')]), | ||
| (bold_hmc_wf, bold_t1_trans_wf, [ | ||
|
|
@@ -516,18 +529,22 @@ def init_func_preproc_wf(bold_file): | |
| # update name source for optimal combination | ||
| (inputnode, func_derivatives_wf, [ | ||
| (('bold_file', combine_meepi_source), 'inputnode.source_file')]), | ||
| (bold_bold_trans_wf, join_echos, [ | ||
| ('outputnode.bold', 'bold_files')]), | ||
| (join_echos, final_boldref_wf, [ | ||
| ('bold_files', 'inputnode.bold_file')]), | ||
effigies marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| (bold_bold_trans_wf, skullstrip_bold_wf, [ | ||
| ('outputnode.bold', 'inputnode.in_file')]), | ||
| (skullstrip_bold_wf, join_echos, [ | ||
| ('outputnode.skull_stripped_file', 'bold_files')]), | ||
| ('outputnode.skull_stripped_file', 'skullstripped_bold_files')]), | ||
| (join_echos, bold_t2s_wf, [ | ||
| ('bold_files', 'inputnode.bold_file')]), | ||
| ('skullstripped_bold_files', 'inputnode.bold_file')]), | ||
| (bold_t2s_wf, bold_confounds_wf, [ | ||
| ('outputnode.bold', 'inputnode.bold')]), | ||
| (bold_t2s_wf, split_opt_comb, [ | ||
| ('outputnode.bold', 'in_file')]), | ||
| (split_opt_comb, bold_t1_trans_wf, [ | ||
| ('out_files', 'inputnode.bold_split')]), | ||
| ('out_files', 'inputnode.bold_split')]) | ||
| ]) | ||
|
|
||
| # Already applied in bold_bold_trans_wf, which inputs to bold_t2s_wf | ||
|
|
@@ -541,7 +558,7 @@ def init_func_preproc_wf(bold_file): | |
| workflow.connect([ | ||
| (inputnode, fmap_unwarp_report_wf, [ | ||
| ('t1w_dseg', 'inputnode.in_seg')]), | ||
| (bold_reference_wf, fmap_unwarp_report_wf, [ | ||
| (initial_boldref_wf, fmap_unwarp_report_wf, [ | ||
| ('outputnode.ref_image', 'inputnode.in_pre')]), | ||
| (bold_reg_wf, fmap_unwarp_report_wf, [ | ||
| ('outputnode.itk_t1_to_bold', 'inputnode.in_xfm')]), | ||
|
|
@@ -578,7 +595,7 @@ def init_func_preproc_wf(bold_file): | |
| workflow.connect([ | ||
| (inputnode, syn_unwarp_report_wf, [ | ||
| ('t1w_dseg', 'inputnode.in_seg')]), | ||
| (bold_reference_wf, syn_unwarp_report_wf, [ | ||
| (initial_boldref_wf, syn_unwarp_report_wf, [ | ||
| ('outputnode.ref_image', 'inputnode.in_pre')]), | ||
| (bold_reg_wf, syn_unwarp_report_wf, [ | ||
| ('outputnode.itk_t1_to_bold', 'inputnode.in_xfm')]), | ||
|
|
@@ -607,19 +624,19 @@ 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, boldmask_to_t1w, [ | ||
| (final_boldref_wf, boldmask_to_t1w, [ | ||
| ('outputnode.bold_mask', 'input_image')]), | ||
| (boldmask_to_t1w, outputnode, [ | ||
| ('output_image', 'bold_mask_t1')]), | ||
| ]) | ||
|
|
||
| if nonstd_spaces.intersection(('func', 'run', 'bold', 'boldref', 'sbref')): | ||
| workflow.connect([ | ||
| (bold_bold_trans_wf, outputnode, [ | ||
| ('outputnode.bold', 'bold_native')]), | ||
| (bold_bold_trans_wf, func_derivatives_wf, [ | ||
| ('outputnode.bold_ref', 'inputnode.bold_native_ref'), | ||
| (final_boldref_wf, func_derivatives_wf, [ | ||
| ('outputnode.ref_image', 'inputnode.bold_native_ref'), | ||
| ('outputnode.bold_mask', 'inputnode.bold_mask_native')]), | ||
| (bold_bold_trans_wf if not multiecho else bold_t2s_wf, outputnode, [ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be a semantic change, not just a reorganization. Was this something we were doing wrong?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, yes, I think it was wrong before, since it took the BOLD files from
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking through, I agree with this change. If I'm reading it right, a native BOLD space derivative for MEEPI will be the optimal combination, which seems appropriate. |
||
| ('outputnode.bold', 'bold_native')]) | ||
| ]) | ||
|
|
||
| if spaces.get_spaces(nonstandard=False, dim=(3,)): | ||
|
|
@@ -640,26 +657,15 @@ def init_func_preproc_wf(bold_file): | |
| ('bold_file', 'inputnode.name_source'), | ||
| ('t1w_aseg', 'inputnode.bold_aseg'), | ||
| ('t1w_aparc', 'inputnode.bold_aparc')]), | ||
| (final_boldref_wf, bold_std_trans_wf, [ | ||
| ('outputnode.bold_mask', 'inputnode.bold_mask')]), | ||
| (bold_reg_wf, bold_std_trans_wf, [ | ||
| ('outputnode.itk_bold_to_t1', 'inputnode.itk_bold_to_t1')]), | ||
| (bold_bold_trans_wf, bold_std_trans_wf, [ | ||
| ('outputnode.bold_mask', 'inputnode.bold_mask')]), | ||
| (bold_std_trans_wf, outputnode, [('outputnode.bold_std', 'bold_std'), | ||
| ('outputnode.bold_std_ref', 'bold_std_ref'), | ||
| ('outputnode.bold_mask_std', 'bold_mask_std')]), | ||
| ]) | ||
|
|
||
| if freesurfer: | ||
| workflow.connect([ | ||
| (bold_std_trans_wf, func_derivatives_wf, [ | ||
| ('outputnode.bold_aseg_std', 'inputnode.bold_aseg_std'), | ||
| ('outputnode.bold_aparc_std', 'inputnode.bold_aparc_std'), | ||
| ]), | ||
| (bold_std_trans_wf, outputnode, [ | ||
| ('outputnode.bold_aseg_std', 'bold_aseg_std'), | ||
| ('outputnode.bold_aparc_std', 'bold_aparc_std')]), | ||
| ]) | ||
|
|
||
| if not multiecho: | ||
| workflow.connect([ | ||
| (bold_split, bold_std_trans_wf, [ | ||
|
|
@@ -672,13 +678,24 @@ def init_func_preproc_wf(bold_file): | |
| else: | ||
| workflow.connect([ | ||
| (split_opt_comb, bold_std_trans_wf, [ | ||
| ('out_files', 'inputnode.bold_split')]) | ||
| ('out_files', 'inputnode.bold_split')]), | ||
tsalo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ]) | ||
|
|
||
| # Already applied in bold_bold_trans_wf, which inputs to bold_t2s_wf | ||
| bold_std_trans_wf.inputs.inputnode.fieldwarp = 'identity' | ||
| bold_std_trans_wf.inputs.inputnode.hmc_xforms = 'identity' | ||
|
|
||
| if freesurfer: | ||
| workflow.connect([ | ||
| (bold_std_trans_wf, func_derivatives_wf, [ | ||
| ('outputnode.bold_aseg_std', 'inputnode.bold_aseg_std'), | ||
| ('outputnode.bold_aparc_std', 'inputnode.bold_aparc_std'), | ||
| ]), | ||
tsalo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| (bold_std_trans_wf, outputnode, [ | ||
| ('outputnode.bold_aseg_std', 'bold_aseg_std'), | ||
| ('outputnode.bold_aparc_std', 'bold_aparc_std')]), | ||
| ]) | ||
|
|
||
| # func_derivatives_wf internally parametrizes over snapshotted spaces. | ||
| workflow.connect([ | ||
| (bold_std_trans_wf, func_derivatives_wf, [ | ||
|
|
@@ -721,7 +738,7 @@ def init_func_preproc_wf(bold_file): | |
| ('bold_file', 'inputnode.name_source')]), | ||
| (bold_hmc_wf, ica_aroma_wf, [ | ||
| ('outputnode.movpar_file', 'inputnode.movpar_file')]), | ||
| (bold_reference_wf, ica_aroma_wf, [ | ||
| (initial_boldref_wf, ica_aroma_wf, [ | ||
| ('outputnode.skip_vols', 'inputnode.skip_vols')]), | ||
| (bold_confounds_wf, join, [ | ||
| ('outputnode.confounds_file', 'in_file')]), | ||
|
|
@@ -815,15 +832,16 @@ def init_func_preproc_wf(bold_file): | |
| ('std2anat_xfm', 'inputnode.std2anat_xfm')]), | ||
| (bold_bold_trans_wf if not multiecho else bold_t2s_wf, carpetplot_wf, [ | ||
| ('outputnode.bold', 'inputnode.bold')]), | ||
| (bold_bold_trans_wf, carpetplot_wf, [ | ||
| (final_boldref_wf, carpetplot_wf, [ | ||
| ('outputnode.bold_mask', 'inputnode.bold_mask')]), | ||
| (bold_reg_wf, carpetplot_wf, [ | ||
| ('outputnode.itk_t1_to_bold', 'inputnode.t1_bold_xform')]), | ||
| ]) | ||
|
|
||
| workflow.connect([ | ||
| (bold_confounds_wf, carpetplot_wf, [ | ||
| ('outputnode.confounds_file', 'inputnode.confounds_file')]) | ||
| ('outputnode.confounds_file', 'inputnode.confounds_file') | ||
| ]) | ||
| ]) | ||
|
|
||
| # REPORTING ############################################################ | ||
|
|
@@ -840,7 +858,7 @@ def init_func_preproc_wf(bold_file): | |
|
|
||
| workflow.connect([ | ||
| (summary, ds_report_summary, [('out_report', 'in_file')]), | ||
| (bold_reference_wf, ds_report_validation, [ | ||
| (initial_boldref_wf, ds_report_validation, [ | ||
| ('outputnode.validation_report', 'in_file')]), | ||
| ]) | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.