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

Write out denoised data to requested output spaces #61

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
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 @@
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 @@
),
)
# 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 @@ -489,8 +490,20 @@
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 495 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L495

Added line #L495 was not covered by tests

templates = spaces.get_spaces()
template_iterator_wf = init_template_iterator_wf(

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

View check run for this annotation

Codecov / codecov/patch

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

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

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

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L502

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

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

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L505

Added line #L505 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 @@ -506,8 +519,63 @@
('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 540 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L538-L540

Added lines #L538 - L540 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 549 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L549

Added line #L549 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 556 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L554-L556

Added lines #L554 - L556 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 560 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L560

Added line #L560 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 566 in src/fmripost_aroma/workflows/base.py

View check run for this annotation

Codecov / codecov/patch

src/fmripost_aroma/workflows/base.py#L566

Added line #L566 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
Loading