Skip to content
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

ENH: Mask multi-echo data with reference mask instead of echo-specific masks #2349

Merged
merged 8 commits into from
Sep 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion fmriprep/interfaces/multiecho.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,14 @@ class T2SMapInputSpec(CommandLineInputSpec):
mandatory=True,
minlen=3,
desc='echo times')
mask_file = File(argstr='--mask',
position=3,
mandatory=False,
desc='mask file',
exists=True)
fittype = traits.Enum('curvefit', 'loglin',
argstr='--fittype %s',
position=3,
position=4,
usedefault=True,
desc=('Desired fitting method: '
'"loglin" means that a linear model is fit '
Expand Down
16 changes: 6 additions & 10 deletions fmriprep/workflows/bold/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,17 +468,14 @@ def init_func_preproc_wf(bold_file, has_fieldmap=False):

# MULTI-ECHO EPI DATA #############################################
if multiecho: # instantiate relevant interfaces, imports
from niworkflows.func.util import init_skullstrip_bold_wf
skullstrip_bold_wf = init_skullstrip_bold_wf(name='skullstrip_bold_wf')

split_opt_comb = bold_split.clone(name='split_opt_comb')

inputnode.inputs.bold_file = ref_file # Replace reference w first echo

join_echos = pe.JoinNode(
niu.IdentityInterface(fields=['bold_files', 'skullstripped_bold_files']),
niu.IdentityInterface(fields=['bold_files']),
joinsource=('meepi_echos' if run_stc is True else 'boldbuffer'),
joinfield=['bold_files', 'skullstripped_bold_files'],
joinfield=['bold_files'],
name='join_echos'
)

Expand Down Expand Up @@ -576,12 +573,11 @@ def init_func_preproc_wf(bold_file, has_fieldmap=False):
('outputnode.bold', 'bold_files')]),
(join_echos, final_boldref_wf, [
('bold_files', 'inputnode.bold_file')]),
(bold_bold_trans_wf, skullstrip_bold_wf, [
('outputnode.bold', 'inputnode.in_file')]),
(skullstrip_bold_wf, join_echos, [
('outputnode.skull_stripped_file', 'skullstripped_bold_files')]),
# use reference image mask used by bold_bold_trans_wf
(bold_bold_trans_wf, bold_t2s_wf, [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be careful to ensure that bold_bold_trans_wf does not depend on bold_t2s_wf. If this assumption is acceptable, then this seems the most reasonable solution to this problem.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that because it would introduce a loop in the workflow? I agree that T2* mapping/optimal combination should happen after the native-space transforms are applied, mostly so that those transforms can be done all at once. There are solid reasons to do optimal combination after distortion correction, but I don't think that will have a very large effect on the data and I doubt that it's worth the extra effort since it would involve splitting up the transforms performed by bold_bold_trans_wf into two sets.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that because it would introduce a loop in the workflow?

Yes, Nipype will not handle loops.

(('outputnode.bold_mask', pop_file), 'inputnode.bold_mask')]),
(join_echos, bold_t2s_wf, [
('skullstripped_bold_files', 'inputnode.bold_file')]),
('bold_files', 'inputnode.bold_file')]),
(bold_t2s_wf, bold_confounds_wf, [
('outputnode.bold', 'inputnode.bold')]),
(bold_t2s_wf, split_opt_comb, [
Expand Down
7 changes: 5 additions & 2 deletions fmriprep/workflows/bold/t2s.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ def init_bold_t2s_wf(echo_times, mem_gb, omp_nthreads,
------
bold_file
list of individual echo files
bold_mask
a binary mask to apply to the BOLD files

Outputs
-------
Expand All @@ -90,7 +92,7 @@ def init_bold_t2s_wf(echo_times, mem_gb, omp_nthreads,
The optimally combined time series was carried forward as the *preprocessed BOLD*.
"""

inputnode = pe.Node(niu.IdentityInterface(fields=['bold_file']), name='inputnode')
inputnode = pe.Node(niu.IdentityInterface(fields=['bold_file', 'bold_mask']), name='inputnode')

outputnode = pe.Node(niu.IdentityInterface(fields=['bold']), name='outputnode')

Expand All @@ -99,7 +101,8 @@ def init_bold_t2s_wf(echo_times, mem_gb, omp_nthreads,
t2smap_node = pe.Node(T2SMap(echo_times=list(echo_times)), name='t2smap_node')

workflow.connect([
(inputnode, t2smap_node, [('bold_file', 'in_files')]),
(inputnode, t2smap_node, [('bold_file', 'in_files'),
('bold_mask', 'mask_file')]),
(t2smap_node, outputnode, [('optimal_comb', 'bold')]),
])

Expand Down