Skip to content

Commit

Permalink
Write out denoised data to requested output spaces (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
tsalo authored Sep 3, 2024
1 parent d84d680 commit 07e904f
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 18 deletions.
33 changes: 16 additions & 17 deletions src/fmripost_aroma/cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ def _build_parser(**kwargs):
from functools import partial
from pathlib import Path

from niworkflows.utils.spaces import OutputReferencesAction

Check warning on line 40 in src/fmripost_aroma/cli/parser.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/cli/parser.py#L40

Added line #L40 was not covered by tests
from packaging.version import Version

from fmripost_aroma.cli.version import check_latest, is_flagged

# from niworkflows.utils.spaces import OutputReferencesAction

class ToDict(Action):
def __call__(self, parser, namespace, values, option_string=None):
d = {}
Expand Down Expand Up @@ -326,21 +325,21 @@ def _bids_filter(value, parser):
),
)
# Disable output spaces until warping works
# g_conf.add_argument(
# '--output-spaces',
# nargs='*',
# action=OutputReferencesAction,
# help="""\
# Standard and non-standard spaces to resample denoised functional images to. \
# Standard spaces may be specified by the form \
# ``<SPACE>[:cohort-<label>][:res-<resolution>][...]``, where ``<SPACE>`` is \
# a keyword designating a spatial reference, and may be followed by optional, \
# colon-separated parameters. \
# Non-standard spaces imply specific orientations and sampling grids. \
# For further details, please check out \
# https://fmriprep.readthedocs.io/en/%s/spaces.html"""
# % (currentv.base_version if is_release else 'latest'),
# )
g_conf.add_argument(

Check warning on line 328 in src/fmripost_aroma/cli/parser.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/cli/parser.py#L328

Added line #L328 was not covered by tests
'--output-spaces',
nargs='*',
action=OutputReferencesAction,
help="""\
Standard and non-standard spaces to resample denoised functional images to. \
Standard spaces may be specified by the form \
``<SPACE>[:cohort-<label>][:res-<resolution>][...]``, where ``<SPACE>`` is \
a keyword designating a spatial reference, and may be followed by optional, \
colon-separated parameters. \
Non-standard spaces imply specific orientations and sampling grids. \
For further details, please check out \
https://fmriprep.readthedocs.io/en/%s/spaces.html"""
% (currentv.base_version if is_release else 'latest'),
)
g_conf.add_argument(
'--dummy-scans',
required=False,
Expand Down
70 changes: 69 additions & 1 deletion src/fmripost_aroma/workflows/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

import yaml
from nipype.pipeline import engine as pe
from niworkflows.interfaces.utility import KeySelect
from packaging.version import Version

from fmripost_aroma import config
Expand Down Expand Up @@ -488,8 +489,20 @@ def init_single_run_wf(bold_file):
func_fit_reports_wf.inputs.inputnode.anat_dseg = functional_cache['anat_dseg']
workflow.connect([(mni6_buffer, func_fit_reports_wf, [('bold', 'inputnode.bold_mni6')])])

if config.workflow.denoise_method:
if config.workflow.denoise_method and spaces.get_spaces():
# Now denoise the output-space BOLD data using ICA-AROMA
from smriprep.workflows.outputs import init_template_iterator_wf

Check warning on line 494 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L494

Added line #L494 was not covered by tests

templates = spaces.get_spaces()
template_iterator_wf = init_template_iterator_wf(

Check warning on line 497 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L496-L497

Added lines #L496 - L497 were not covered by tests
spaces=spaces,
sloppy=config.execution.sloppy,
)
template_iterator_wf.inputs.inputnode.anat2std_xfm = functional_cache[

Check warning on line 501 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L501

Added line #L501 was not covered by tests
'anat2outputspaces_xfm'
]
template_iterator_wf.inputs.inputnode.template = templates

Check warning on line 504 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L504

Added line #L504 was not covered by tests

denoise_wf = init_denoise_wf(bold_file=bold_file, metadata=bold_metadata)
denoise_wf.inputs.inputnode.skip_vols = skip_vols
denoise_wf.inputs.inputnode.space = 'MNI152NLin6Asym'
Expand All @@ -505,8 +518,63 @@ def init_single_run_wf(bold_file):
('outputnode.mixing', 'inputnode.mixing'),
('outputnode.aroma_features', 'inputnode.classifications'),
]),
(template_iterator_wf, denoise_wf, [
('outputnode.space', 'inputnode.space'),
('outputnode.cohort', 'inputnode.cohort'),
('outputnode.res', 'inputnode.res'),
]),
]) # fmt:skip

if functional_cache['bold_outputspaces']:
# No transforms necessary
std_buffer = pe.Node(
KeySelect(
fields=['bold', 'bold_mask'],
keys=[str(space) for space in spaces.references],
),
name='std_buffer',
)
std_buffer.inputs.bold = functional_cache['bold_outputspaces']
std_buffer.inputs.bold_mask = functional_cache['bold_mask_outputspaces']
workflow.connect([

Check warning on line 539 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L537-L539

Added lines #L537 - L539 were not covered by tests
(template_iterator_wf, std_buffer, [('outputnode.space', 'key')]),
(std_buffer, denoise_wf, [
('bold', 'inputnode.bold_file'),
('bold_mask', 'inputnode.bold_mask'),
]),
]) # fmt:skip
else:
# Warp native BOLD to requested output spaces
xfms = [

Check warning on line 548 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L548

Added line #L548 was not covered by tests
functional_cache['hmc'],
functional_cache['boldref2fmap'],
functional_cache['bold2anat'],
]
all_xfms = pe.Node(niu.Merge(2), name='all_xfms')
all_xfms.inputs.in1 = xfms
workflow.connect([

Check warning on line 555 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L553-L555

Added lines #L553 - L555 were not covered by tests
(template_iterator_wf, all_xfms, [('outputnode.anat2std_xfm', 'in2')]),
]) # fmt:skip

resample_std_wf = init_resample_volumetric_wf(

Check warning on line 559 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L559

Added line #L559 was not covered by tests
bold_file=bold_file,
functional_cache=functional_cache,
run_stc=False,
name=_get_wf_name(bold_file, 'resample_std'),
)
workflow.connect([

Check warning on line 565 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L565

Added line #L565 was not covered by tests
(template_iterator_wf, resample_std_wf, [
('outputnode.space', 'inputnode.space'),
('outputnode.res', 'inputnode.res'),
('outputnode.cohort', 'inputnode.cohort'),
]),
(all_xfms, resample_std_wf, [('out', 'inputnode.transforms')]),
(resample_std_wf, denoise_wf, [
('outputnode.bold_std', 'inputnode.bold'),
('outputnode.bold_mask_std', 'inputnode.bold_mask'),
]),
]) # fmt:skip

# Fill-in datasinks seen so far
for node in workflow.list_node_names():
if node.split('.')[-1].startswith('ds_'):
Expand Down

0 comments on commit 07e904f

Please sign in to comment.