forked from nipreps/fmriprep
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TEST: Add smoke-tests for bold_fit_wf (nipreps#3152)
Turns out testing's a good idea. Starting out doing something similar to nipreps/smriprep#390. Will try to expand the smoke tests upward to `workflows.bold.base` and `workflows.base`.
- Loading branch information
Showing
7 changed files
with
308 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
from pathlib import Path | ||
|
||
import nibabel as nb | ||
import numpy as np | ||
import pytest | ||
from nipype.pipeline.engine.utils import generate_expanded_graph | ||
from niworkflows.utils.testing import generate_bids_skeleton | ||
|
||
from .... import config | ||
from ...tests import mock_config | ||
from ...tests.test_base import BASE_LAYOUT | ||
from ..base import init_bold_wf | ||
|
||
|
||
@pytest.fixture(scope="module", autouse=True) | ||
def _quiet_logger(): | ||
import logging | ||
|
||
logger = logging.getLogger("nipype.workflow") | ||
old_level = logger.getEffectiveLevel() | ||
logger.setLevel(logging.ERROR) | ||
yield | ||
logger.setLevel(old_level) | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def bids_root(tmp_path_factory): | ||
base = tmp_path_factory.mktemp("boldbase") | ||
bids_dir = base / "bids" | ||
generate_bids_skeleton(bids_dir, BASE_LAYOUT) | ||
yield bids_dir | ||
|
||
|
||
@pytest.mark.parametrize("task", ["rest", "nback"]) | ||
@pytest.mark.parametrize("fieldmap_id", ["phasediff", None]) | ||
@pytest.mark.parametrize("freesurfer", [False, True]) | ||
@pytest.mark.parametrize("level", ["minimal", "resampling", "full"]) | ||
def test_bold_wf( | ||
bids_root: Path, | ||
tmp_path: Path, | ||
task: str, | ||
fieldmap_id: str | None, | ||
freesurfer: bool, | ||
level: str, | ||
): | ||
"""Test as many combinations of precomputed files and input | ||
configurations as possible.""" | ||
output_dir = tmp_path / 'output' | ||
output_dir.mkdir() | ||
|
||
img = nb.Nifti1Image(np.zeros((10, 10, 10, 10)), np.eye(4)) | ||
|
||
if task == 'rest': | ||
bold_series = [ | ||
str(bids_root / 'sub-01' / 'func' / 'sub-01_task-rest_run-1_bold.nii.gz'), | ||
] | ||
elif task == 'nback': | ||
bold_series = [ | ||
str(bids_root / 'sub-01' / 'func' / f'sub-01_task-nback_echo-{i}_bold.nii.gz') | ||
for i in range(1, 4) | ||
] | ||
|
||
# The workflow will attempt to read file headers | ||
for path in bold_series: | ||
img.to_filename(path) | ||
|
||
with mock_config(bids_dir=bids_root): | ||
config.workflow.level = level | ||
config.workflow.run_reconall = freesurfer | ||
wf = init_bold_wf( | ||
bold_series=bold_series, | ||
fieldmap_id=fieldmap_id, | ||
precomputed={}, | ||
) | ||
|
||
flatgraph = wf._create_flat_graph() | ||
generate_expanded_graph(flatgraph) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
from pathlib import Path | ||
|
||
import nibabel as nb | ||
import numpy as np | ||
import pytest | ||
from nipype.pipeline.engine.utils import generate_expanded_graph | ||
from niworkflows.utils.testing import generate_bids_skeleton | ||
|
||
from .... import config | ||
from ...tests import mock_config | ||
from ...tests.test_base import BASE_LAYOUT | ||
from ..fit import init_bold_fit_wf, init_bold_native_wf | ||
|
||
|
||
@pytest.fixture(scope="module", autouse=True) | ||
def _quiet_logger(): | ||
import logging | ||
|
||
logger = logging.getLogger("nipype.workflow") | ||
old_level = logger.getEffectiveLevel() | ||
logger.setLevel(logging.ERROR) | ||
yield | ||
logger.setLevel(old_level) | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def bids_root(tmp_path_factory): | ||
base = tmp_path_factory.mktemp("boldfit") | ||
bids_dir = base / "bids" | ||
generate_bids_skeleton(bids_dir, BASE_LAYOUT) | ||
yield bids_dir | ||
|
||
|
||
def _make_params( | ||
have_hmcref: bool = True, | ||
have_coregref: bool = True, | ||
have_hmc_xfms: bool = True, | ||
have_boldref2fmap_xfm: bool = True, | ||
have_boldref2anat_xfm: bool = True, | ||
): | ||
return ( | ||
have_hmcref, | ||
have_coregref, | ||
have_hmc_xfms, | ||
have_boldref2anat_xfm, | ||
have_boldref2fmap_xfm, | ||
) | ||
|
||
|
||
@pytest.mark.parametrize("task", ["rest", "nback"]) | ||
@pytest.mark.parametrize("fieldmap_id", ["phasediff", None]) | ||
@pytest.mark.parametrize( | ||
( | ||
'have_hmcref', | ||
'have_coregref', | ||
'have_hmc_xfms', | ||
'have_boldref2fmap_xfm', | ||
'have_boldref2anat_xfm', | ||
), | ||
[ | ||
(True, True, True, True, True), | ||
(False, False, False, False, False), | ||
_make_params(have_hmcref=False), | ||
_make_params(have_hmc_xfms=False), | ||
_make_params(have_coregref=False), | ||
_make_params(have_coregref=False, have_boldref2fmap_xfm=False), | ||
_make_params(have_boldref2anat_xfm=False), | ||
], | ||
) | ||
def test_bold_fit_precomputes( | ||
bids_root: Path, | ||
tmp_path: Path, | ||
task: str, | ||
fieldmap_id: str | None, | ||
have_hmcref: bool, | ||
have_coregref: bool, | ||
have_hmc_xfms: bool, | ||
have_boldref2fmap_xfm: bool, | ||
have_boldref2anat_xfm: bool, | ||
): | ||
"""Test as many combinations of precomputed files and input | ||
configurations as possible.""" | ||
output_dir = tmp_path / 'output' | ||
output_dir.mkdir() | ||
|
||
img = nb.Nifti1Image(np.zeros((10, 10, 10, 10)), np.eye(4)) | ||
|
||
if task == 'rest': | ||
bold_series = [ | ||
str(bids_root / 'sub-01' / 'func' / 'sub-01_task-rest_run-1_bold.nii.gz'), | ||
] | ||
elif task == 'nback': | ||
bold_series = [ | ||
str(bids_root / 'sub-01' / 'func' / f'sub-01_task-nback_echo-{i}_bold.nii.gz') | ||
for i in range(1, 4) | ||
] | ||
|
||
# The workflow will attempt to read file headers | ||
for path in bold_series: | ||
img.to_filename(path) | ||
|
||
dummy_nifti = str(tmp_path / 'dummy.nii') | ||
dummy_affine = str(tmp_path / 'dummy.txt') | ||
img.to_filename(dummy_nifti) | ||
np.savetxt(dummy_affine, np.eye(4)) | ||
|
||
# Construct precomputed files | ||
precomputed = {'transforms': {}} | ||
if have_hmcref: | ||
precomputed['hmc_boldref'] = dummy_nifti | ||
if have_coregref: | ||
precomputed['coreg_boldref'] = dummy_nifti | ||
if have_hmc_xfms: | ||
precomputed['transforms']['hmc'] = dummy_affine | ||
if have_boldref2anat_xfm: | ||
precomputed['transforms']['boldref2anat'] = dummy_affine | ||
if have_boldref2fmap_xfm: | ||
precomputed['transforms']['boldref2fmap'] = dummy_affine | ||
|
||
with mock_config(bids_dir=bids_root): | ||
wf = init_bold_fit_wf( | ||
bold_series=bold_series, | ||
precomputed=precomputed, | ||
fieldmap_id=fieldmap_id, | ||
omp_nthreads=1, | ||
) | ||
|
||
flatgraph = wf._create_flat_graph() | ||
generate_expanded_graph(flatgraph) | ||
|
||
|
||
@pytest.mark.parametrize("task", ["rest", "nback"]) | ||
@pytest.mark.parametrize("fieldmap_id", ["phasediff", None]) | ||
@pytest.mark.parametrize("run_stc", [True, False]) | ||
def test_bold_native_precomputes( | ||
bids_root: Path, | ||
tmp_path: Path, | ||
task: str, | ||
fieldmap_id: str | None, | ||
run_stc: bool, | ||
): | ||
"""Test as many combinations of precomputed files and input | ||
configurations as possible.""" | ||
output_dir = tmp_path / 'output' | ||
output_dir.mkdir() | ||
|
||
img = nb.Nifti1Image(np.zeros((10, 10, 10, 10)), np.eye(4)) | ||
|
||
if task == 'rest': | ||
bold_series = [ | ||
str(bids_root / 'sub-01' / 'func' / 'sub-01_task-rest_run-1_bold.nii.gz'), | ||
] | ||
elif task == 'nback': | ||
bold_series = [ | ||
str(bids_root / 'sub-01' / 'func' / f'sub-01_task-nback_echo-{i}_bold.nii.gz') | ||
for i in range(1, 4) | ||
] | ||
|
||
# The workflow will attempt to read file headers | ||
for path in bold_series: | ||
img.to_filename(path) | ||
|
||
with mock_config(bids_dir=bids_root): | ||
config.workflow.ignore = ['slicetiming'] if not run_stc else [] | ||
wf = init_bold_native_wf( | ||
bold_series=bold_series, | ||
fieldmap_id=fieldmap_id, | ||
omp_nthreads=1, | ||
) | ||
|
||
flatgraph = wf._create_flat_graph() | ||
generate_expanded_graph(flatgraph) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.