Skip to content

Commit f759acb

Browse files
fix broken unit tests
1 parent 162f8fc commit f759acb

File tree

2 files changed

+188
-165
lines changed

2 files changed

+188
-165
lines changed
Lines changed: 0 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
from pathlib import Path
2-
from unittest.mock import patch
3-
4-
import nibabel as nib
5-
import numpy as np
61
import pytest
7-
from numpy.testing import assert_array_equal
82

93

104
@pytest.mark.parametrize("suffix", ["T1w", "FLAIR", "fooo"])
@@ -30,162 +24,3 @@ def test_get_substitutions_datasink(suffix):
3024
f"sub-ADNI022S0004_ses-M000_{suffix}Warped.nii.gz",
3125
f"sub-ADNI022S0004_ses-M000_space-MNI152NLin2009cSym_res-1x1x1_{suffix}.nii.gz",
3226
)
33-
34-
35-
def n4biasfieldcorrection_mock(
36-
input_image: Path,
37-
bspline_fitting_distance: int,
38-
save_bias: bool = False,
39-
verbose: bool = False,
40-
):
41-
"""The mock simply returns the input image without any processing."""
42-
return nib.load(input_image)
43-
44-
45-
def test_run_n4biasfieldcorrection_no_bias_saving(tmp_path):
46-
from clinica.pipelines.t1_linear.anat_linear_utils import run_n4biasfieldcorrection
47-
48-
data = np.random.random((10, 10, 10))
49-
nib.save(nib.Nifti1Image(data, np.eye(4)), tmp_path / "test.nii.gz")
50-
output_dir = tmp_path / "out"
51-
output_dir.mkdir()
52-
53-
with patch("ants.image_write", wraps=nib.save) as image_write_mock:
54-
with patch(
55-
"clinica.pipelines.t1_linear.anat_linear_utils._call_n4_bias_field_correction",
56-
wraps=n4biasfieldcorrection_mock,
57-
) as ants_bias_correction_mock:
58-
bias_corrected_image = run_n4biasfieldcorrection(
59-
tmp_path / "test.nii.gz",
60-
bspline_fitting_distance=300,
61-
output_prefix="sub-01_ses-M000",
62-
output_dir=output_dir,
63-
)
64-
image_write_mock.assert_called_once()
65-
ants_bias_correction_mock.assert_called_once_with(
66-
tmp_path / "test.nii.gz",
67-
300,
68-
save_bias=False,
69-
verbose=False,
70-
)
71-
# Verify that the bias corrected image exists
72-
# If all went well, it will be the same as the input image because of the mocks.
73-
assert [f.name for f in output_dir.iterdir()] == [
74-
"sub-01_ses-M000_bias_corrected_image.nii.gz"
75-
]
76-
assert bias_corrected_image.exists()
77-
bias_corrected_nifti = nib.load(bias_corrected_image)
78-
assert_array_equal(bias_corrected_nifti.affine, np.eye(4))
79-
assert_array_equal(bias_corrected_nifti.get_fdata(), data)
80-
81-
82-
def test_run_n4biasfieldcorrection(tmp_path):
83-
from clinica.pipelines.t1_linear.anat_linear_utils import run_n4biasfieldcorrection
84-
85-
data = np.random.random((10, 10, 10))
86-
nib.save(nib.Nifti1Image(data, np.eye(4)), tmp_path / "test.nii.gz")
87-
output_dir = tmp_path / "out"
88-
output_dir.mkdir()
89-
90-
with patch("ants.image_write", wraps=nib.save) as image_write_mock:
91-
with patch(
92-
"clinica.pipelines.t1_linear.anat_linear_utils._call_n4_bias_field_correction",
93-
wraps=n4biasfieldcorrection_mock,
94-
) as ants_bias_correction_mock:
95-
bias_corrected_image = run_n4biasfieldcorrection(
96-
tmp_path / "test.nii.gz",
97-
bspline_fitting_distance=300,
98-
output_prefix="sub-01_ses-M000",
99-
output_dir=output_dir,
100-
save_bias=True,
101-
verbose=True,
102-
)
103-
image_write_mock.assert_called()
104-
ants_bias_correction_mock.assert_called_with(
105-
tmp_path / "test.nii.gz",
106-
300,
107-
save_bias=True,
108-
verbose=True,
109-
)
110-
assert set([f.name for f in output_dir.iterdir()]) == {
111-
"sub-01_ses-M000_bias_corrected_image.nii.gz",
112-
"sub-01_ses-M000_bias_image.nii.gz",
113-
}
114-
assert bias_corrected_image.exists()
115-
bias_corrected_nifti = nib.load(bias_corrected_image)
116-
assert_array_equal(bias_corrected_nifti.affine, np.eye(4))
117-
assert_array_equal(bias_corrected_nifti.get_fdata(), data)
118-
119-
120-
def generate_fake_fixed_and_moving_images(folder: Path):
121-
data = np.random.random((10, 10, 10))
122-
nib.save(nib.Nifti1Image(data, np.eye(4)), folder / "fixed.nii.gz")
123-
nib.save(nib.Nifti1Image(data, np.eye(4)), folder / "moving.nii.gz")
124-
125-
126-
def test_run_ants_registration_error(tmp_path, mocker):
127-
import re
128-
129-
from clinica.pipelines.t1_linear.anat_linear_utils import run_ants_registration
130-
131-
generate_fake_fixed_and_moving_images(tmp_path)
132-
mocker.patch(
133-
"clinica.pipelines.t1_linear.anat_linear_utils._call_ants_registration",
134-
return_value={},
135-
)
136-
with pytest.raises(
137-
RuntimeError,
138-
match=re.escape(
139-
"Something went wrong when calling antsRegistration with the following parameters :\n"
140-
f"- fixed_image = {tmp_path / 'fixed.nii.gz'}\n"
141-
f"- moving_image = {tmp_path / 'moving.nii.gz'}\n"
142-
f"- random_seed = 0\n"
143-
f"- type_of_transformation='antsRegistrationSyN[a]'\n"
144-
),
145-
):
146-
run_ants_registration(
147-
tmp_path / "fixed.nii.gz",
148-
tmp_path / "moving.nii.gz",
149-
random_seed=0,
150-
)
151-
152-
153-
def ants_registration_mock(
154-
fixed_image: Path,
155-
moving_image: Path,
156-
random_seed: int,
157-
verbose: bool = False,
158-
) -> dict:
159-
workdir = fixed_image.parent / "workdir"
160-
workdir.mkdir()
161-
mocked_transform = workdir / "transform.mat"
162-
mocked_transform.touch()
163-
return {
164-
"warpedmovout": nib.load(fixed_image),
165-
"fwdtransforms": ["fooo.txt", mocked_transform],
166-
"foo": "bar",
167-
}
168-
169-
170-
def test_run_ants_registration(tmp_path):
171-
from clinica.pipelines.t1_linear.anat_linear_utils import run_ants_registration
172-
173-
output_dir = tmp_path / "out"
174-
output_dir.mkdir()
175-
generate_fake_fixed_and_moving_images(tmp_path)
176-
177-
with patch(
178-
"clinica.pipelines.t1_linear.anat_linear_utils._call_ants_registration",
179-
wraps=ants_registration_mock,
180-
) as mock1:
181-
with patch("ants.image_write", wraps=nib.save) as mock2:
182-
run_ants_registration(
183-
tmp_path / "fixed.nii.gz",
184-
tmp_path / "moving.nii.gz",
185-
random_seed=12,
186-
output_dir=output_dir,
187-
)
188-
mock1.assert_called_once_with(
189-
tmp_path / "fixed.nii.gz", tmp_path / "moving.nii.gz", 12, verbose=False
190-
)
191-
mock2.assert_called_once()
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
from pathlib import Path
2+
from typing import Optional, Tuple, Union
3+
from unittest.mock import patch
4+
5+
import nibabel as nib
6+
import numpy as np
7+
import pytest
8+
from numpy.testing import assert_array_equal
9+
10+
from clinica.pipelines.utils import (
11+
AntsRegistrationSynQuickTransformType,
12+
AntsRegistrationTransformType,
13+
)
14+
15+
16+
def n4biasfieldcorrection_mock(
17+
input_image: Path,
18+
bspline_fitting_distance: int,
19+
save_bias: bool = False,
20+
verbose: bool = False,
21+
):
22+
"""The mock simply returns the input image without any processing."""
23+
return nib.load(input_image)
24+
25+
26+
def test_run_n4biasfieldcorrection_no_bias_saving(tmp_path):
27+
from clinica.pipelines.utils import run_n4biasfieldcorrection
28+
29+
data = np.random.random((10, 10, 10))
30+
nib.save(nib.Nifti1Image(data, np.eye(4)), tmp_path / "test.nii.gz")
31+
output_dir = tmp_path / "out"
32+
output_dir.mkdir()
33+
34+
with patch("ants.image_write", wraps=nib.save) as image_write_mock:
35+
with patch(
36+
"clinica.pipelines.utils._call_n4_bias_field_correction",
37+
wraps=n4biasfieldcorrection_mock,
38+
) as ants_bias_correction_mock:
39+
bias_corrected_image = run_n4biasfieldcorrection(
40+
tmp_path / "test.nii.gz",
41+
bspline_fitting_distance=300,
42+
output_prefix="sub-01_ses-M000",
43+
output_dir=output_dir,
44+
)
45+
image_write_mock.assert_called_once()
46+
ants_bias_correction_mock.assert_called_once_with(
47+
tmp_path / "test.nii.gz",
48+
300,
49+
save_bias=False,
50+
verbose=False,
51+
)
52+
# Verify that the bias corrected image exists
53+
# If all went well, it will be the same as the input image because of the mocks.
54+
assert [f.name for f in output_dir.iterdir()] == [
55+
"sub-01_ses-M000_bias_corrected_image.nii.gz"
56+
]
57+
assert bias_corrected_image.exists()
58+
bias_corrected_nifti = nib.load(bias_corrected_image)
59+
assert_array_equal(bias_corrected_nifti.affine, np.eye(4))
60+
assert_array_equal(bias_corrected_nifti.get_fdata(), data)
61+
62+
63+
def test_run_n4biasfieldcorrection(tmp_path):
64+
from clinica.pipelines.utils import run_n4biasfieldcorrection
65+
66+
data = np.random.random((10, 10, 10))
67+
nib.save(nib.Nifti1Image(data, np.eye(4)), tmp_path / "test.nii.gz")
68+
output_dir = tmp_path / "out"
69+
output_dir.mkdir()
70+
71+
with patch("ants.image_write", wraps=nib.save) as image_write_mock:
72+
with patch(
73+
"clinica.pipelines.utils._call_n4_bias_field_correction",
74+
wraps=n4biasfieldcorrection_mock,
75+
) as ants_bias_correction_mock:
76+
bias_corrected_image = run_n4biasfieldcorrection(
77+
tmp_path / "test.nii.gz",
78+
bspline_fitting_distance=300,
79+
output_prefix="sub-01_ses-M000",
80+
output_dir=output_dir,
81+
save_bias=True,
82+
verbose=True,
83+
)
84+
image_write_mock.assert_called()
85+
ants_bias_correction_mock.assert_called_with(
86+
tmp_path / "test.nii.gz",
87+
300,
88+
save_bias=True,
89+
verbose=True,
90+
)
91+
assert set([f.name for f in output_dir.iterdir()]) == {
92+
"sub-01_ses-M000_bias_corrected_image.nii.gz",
93+
"sub-01_ses-M000_bias_image.nii.gz",
94+
}
95+
assert bias_corrected_image.exists()
96+
bias_corrected_nifti = nib.load(bias_corrected_image)
97+
assert_array_equal(bias_corrected_nifti.affine, np.eye(4))
98+
assert_array_equal(bias_corrected_nifti.get_fdata(), data)
99+
100+
101+
def generate_fake_fixed_and_moving_images(folder: Path):
102+
data = np.random.random((10, 10, 10))
103+
nib.save(nib.Nifti1Image(data, np.eye(4)), folder / "fixed.nii.gz")
104+
nib.save(nib.Nifti1Image(data, np.eye(4)), folder / "moving.nii.gz")
105+
106+
107+
def test_run_ants_registration_synquick_error(tmp_path, mocker):
108+
import re
109+
110+
from clinica.pipelines.utils import run_ants_registration_synquick
111+
112+
generate_fake_fixed_and_moving_images(tmp_path)
113+
mocker.patch(
114+
"clinica.pipelines.utils._call_ants_registration",
115+
return_value={},
116+
)
117+
with pytest.raises(
118+
RuntimeError,
119+
match=re.escape(
120+
"Something went wrong when calling antsRegistration with the following parameters :\n"
121+
f"- fixed_image = {tmp_path / 'fixed.nii.gz'}\n"
122+
f"- moving_image = {tmp_path / 'moving.nii.gz'}\n"
123+
f"- random_seed = 0\n"
124+
f"- type_of_transformation='antsRegistrationSyN[a]'\n"
125+
),
126+
):
127+
run_ants_registration_synquick(
128+
tmp_path / "fixed.nii.gz",
129+
tmp_path / "moving.nii.gz",
130+
random_seed=0,
131+
transform_type=AntsRegistrationSynQuickTransformType.AFFINE,
132+
)
133+
134+
135+
def ants_registration_mock(
136+
fixed_image: Path,
137+
moving_image: Path,
138+
random_seed: int,
139+
transform_type: Union[
140+
AntsRegistrationTransformType, AntsRegistrationSynQuickTransformType
141+
],
142+
verbose: bool = False,
143+
shrink_factors: Optional[Tuple[int, ...]] = None,
144+
smoothing_sigmas: Optional[Tuple[int, ...]] = None,
145+
number_of_iterations: Optional[Tuple[int, ...]] = None,
146+
) -> dict:
147+
workdir = fixed_image.parent / "workdir"
148+
workdir.mkdir()
149+
mocked_transform = workdir / "transform.mat"
150+
mocked_transform.touch()
151+
return {
152+
"warpedmovout": nib.load(fixed_image),
153+
"fwdtransforms": ["fooo.txt", mocked_transform],
154+
"invtransforms": [mocked_transform],
155+
"foo": "bar",
156+
}
157+
158+
159+
def test_run_ants_registration_synquick(tmp_path):
160+
from clinica.pipelines.utils import run_ants_registration_synquick
161+
162+
output_dir = tmp_path / "out"
163+
output_dir.mkdir()
164+
generate_fake_fixed_and_moving_images(tmp_path)
165+
166+
with patch(
167+
"clinica.pipelines.utils._call_ants_registration",
168+
wraps=ants_registration_mock,
169+
) as mock1:
170+
with patch("ants.image_write", wraps=nib.save) as mock2:
171+
run_ants_registration_synquick(
172+
tmp_path / "fixed.nii.gz",
173+
tmp_path / "moving.nii.gz",
174+
random_seed=12,
175+
transform_type=AntsRegistrationSynQuickTransformType.AFFINE,
176+
output_dir=output_dir,
177+
)
178+
mock1.assert_called_once_with(
179+
tmp_path / "fixed.nii.gz",
180+
tmp_path / "moving.nii.gz",
181+
12,
182+
AntsRegistrationSynQuickTransformType.AFFINE,
183+
verbose=False,
184+
shrink_factors=None,
185+
smoothing_sigmas=None,
186+
number_of_iterations=None,
187+
)
188+
mock2.assert_called_once()

0 commit comments

Comments
 (0)