Skip to content

Commit

Permalink
nufft vs fft consistancy
Browse files Browse the repository at this point in the history
  • Loading branch information
fzimmermann89 committed Nov 15, 2024
1 parent 614f7e1 commit 5c29809
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ def ismrmrd_cart(ellipse_phantom, tmp_path_factory):
'2d_cartesian_irregular_sampling',
'2d_single_shot_spiral',
'3d_nonuniform_4_coils_2_other',
'2d_nnonuniform_cine_mri_8_cardiac_phases_5_coils',
'2d_nonuniform_cine_mri_8_cardiac_phases_5_coils',
'2d_cartesian_cine_9_cardiac_phases_6_coils',
'radial_phase_encoding_8_coils_with_oversampling',
'radial_phase_encoding_8_coils_non_cartesian_sampling',
Expand Down
50 changes: 49 additions & 1 deletion tests/operators/test_fourier_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest
import torch
from mrpro.data import KData, KTrajectory, SpatialDimension
from mrpro.data.enums import TrajType
from mrpro.data.traj_calculators import KTrajectoryCartesian
from mrpro.operators import FourierOp

Expand Down Expand Up @@ -64,10 +65,57 @@ def test_fourier_op_norm(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, typ
)
fourier_op = FourierOp(recon_matrix=recon_matrix, encoding_matrix=encoding_matrix, traj=trajectory)
# only do few iterations to speed up the test
norm = fourier_op.operator_norm(img, dim=None, max_iterations=4)
norm = fourier_op.operator_norm(img, dim=None, max_iterations=20)
torch.testing.assert_close(norm.squeeze(), torch.tensor(1.0), atol=0.1, rtol=0.0)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_norm[2d_cartesian_irregular_sampling] AssertionError: Scalars are not close! Expected 1.0 but got 0.7061904668807983. Absolute difference: 0.29380953311920166 (up to 0.1 allowed) Relative difference: 0.29380953311920166 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_norm[2d_single_shot_spiral] AssertionError: Scalars are not close! Expected 1.0 but got 0.7028827667236328. Absolute difference: 0.2971172332763672 (up to 0.1 allowed) Relative difference: 0.2971172332763672 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_norm[3d_nonuniform_4_coils_2_other] AssertionError: Scalars are not close! Expected 1.0 but got 0.8287667632102966. Absolute difference: 0.17123323678970337 (up to 0.1 allowed) Relative difference: 0.17123323678970337 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_norm[radial_phase_encoding_8_coils_with_oversampling] AssertionError: Scalars are not close! Expected 1.0 but got 0.8637340664863586. Absolute difference: 0.13626593351364136 (up to 0.1 allowed) Relative difference: 0.13626593351364136 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_norm[radial_phase_encoding_8_coils_non_cartesian_sampling] AssertionError: Scalars are not close! Expected 1.0 but got 1.5305140018463135. Absolute difference: 0.5305140018463135 (up to 0.1 allowed) Relative difference: 0.5305140018463135 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_norm[stack_of_stars_5_other_3_coil_with_oversampling] AssertionError: Scalars are not close! Expected 1.0 but got 1.3819990158081055. Absolute difference: 0.38199901580810547 (up to 0.1 allowed) Relative difference: 0.38199901580810547 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_norm[2d_cartesian_irregular_sampling] AssertionError: Scalars are not close! Expected 1.0 but got 0.7061904668807983. Absolute difference: 0.29380953311920166 (up to 0.1 allowed) Relative difference: 0.29380953311920166 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_norm[2d_single_shot_spiral] AssertionError: Scalars are not close! Expected 1.0 but got 0.7028827667236328. Absolute difference: 0.2971172332763672 (up to 0.1 allowed) Relative difference: 0.2971172332763672 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_norm[3d_nonuniform_4_coils_2_other] AssertionError: Scalars are not close! Expected 1.0 but got 0.8287667632102966. Absolute difference: 0.17123323678970337 (up to 0.1 allowed) Relative difference: 0.17123323678970337 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_norm[radial_phase_encoding_8_coils_with_oversampling] AssertionError: Scalars are not close! Expected 1.0 but got 0.8637340664863586. Absolute difference: 0.13626593351364136 (up to 0.1 allowed) Relative difference: 0.13626593351364136 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_norm[radial_phase_encoding_8_coils_non_cartesian_sampling] AssertionError: Scalars are not close! Expected 1.0 but got 1.5305140018463135. Absolute difference: 0.5305140018463135 (up to 0.1 allowed) Relative difference: 0.5305140018463135 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_norm[stack_of_stars_5_other_3_coil_with_oversampling] AssertionError: Scalars are not close! Expected 1.0 but got 1.3819990158081055. Absolute difference: 0.38199901580810547 (up to 0.1 allowed) Relative difference: 0.38199901580810547 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_norm[2d_cartesian_irregular_sampling] AssertionError: Scalars are not close! Expected 1.0 but got 0.7061904668807983. Absolute difference: 0.29380953311920166 (up to 0.1 allowed) Relative difference: 0.29380953311920166 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_norm[2d_single_shot_spiral] AssertionError: Scalars are not close! Expected 1.0 but got 0.7028827667236328. Absolute difference: 0.2971172332763672 (up to 0.1 allowed) Relative difference: 0.2971172332763672 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_norm[radial_phase_encoding_8_coils_with_oversampling] AssertionError: Scalars are not close! Expected 1.0 but got 0.8637340664863586. Absolute difference: 0.13626593351364136 (up to 0.1 allowed) Relative difference: 0.13626593351364136 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_norm[3d_nonuniform_4_coils_2_other] AssertionError: Scalars are not close! Expected 1.0 but got 0.8287667632102966. Absolute difference: 0.17123323678970337 (up to 0.1 allowed) Relative difference: 0.17123323678970337 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_norm[radial_phase_encoding_8_coils_non_cartesian_sampling] AssertionError: Scalars are not close! Expected 1.0 but got 1.5305140018463135. Absolute difference: 0.5305140018463135 (up to 0.1 allowed) Relative difference: 0.5305140018463135 (up to 0.0 allowed)

Check failure on line 69 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_norm[stack_of_stars_5_other_3_coil_with_oversampling] AssertionError: Scalars are not close! Expected 1.0 but got 1.3819990158081055. Absolute difference: 0.38199901580810547 (up to 0.1 allowed) Relative difference: 0.38199901580810547 (up to 0.0 allowed)


@COMMON_MR_TRAJECTORIES
def test_fourier_op_fft_nufft(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz, type_k0, type_k1, type_k2):
"""Test Nufft vs FFT for Fourier operator."""

# generate random images and k-space trajectories
img, trajectory = create_data(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz)

# create operator
recon_matrix = SpatialDimension(im_shape[-3], im_shape[-2], im_shape[-1])
encoding_matrix = SpatialDimension(
int(trajectory.kz.max() - trajectory.kz.min() + 1),
int(trajectory.ky.max() - trajectory.ky.min() + 1),
int(trajectory.kx.max() - trajectory.kx.min() + 1),
)
fourier_op = FourierOp(recon_matrix=recon_matrix, encoding_matrix=encoding_matrix, traj=trajectory)

class NufftTrajektory(KTrajectory):
"""Always returns non-grid trajectory type."""

def _traj_types(
self,
tolerance: float,
) -> tuple[tuple[TrajType, TrajType, TrajType], tuple[TrajType, TrajType, TrajType]]:
true_types = super()._traj_types(tolerance)
modified = tuple([tuple([t & (~TrajType.ONGRID) for t in ts]) for ts in true_types])
return modified

nufft_fourier_op = FourierOp(
recon_matrix=recon_matrix,
encoding_matrix=encoding_matrix,
traj=NufftTrajektory(trajectory.kz, trajectory.ky, trajectory.kx),
)

(result_normal,) = fourier_op(img)
(result_nufft,) = nufft_fourier_op(img)
torch.testing.assert_close(result_normal, result_nufft, atol=1e-5, rtol=1e-4)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_fft_nufft[2d_cartesian_1_coil_no_oversampling] AssertionError: Tensor-likes are not close! Mismatched elements: 12288 / 12288 (100.0%) Greatest absolute difference: 0.9110996127128601 at index (0, 0, 0, 70, 56) (up to 1e-05 allowed) Greatest relative difference: 1.0034971237182617 at index (0, 0, 0, 65, 81) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_fft_nufft[2d_cartesian_1_coil_with_oversampling] AssertionError: Tensor-likes are not close! Mismatched elements: 24576 / 24576 (100.0%) Greatest absolute difference: 0.3774434030056 at index (0, 0, 0, 93, 84) (up to 1e-05 allowed) Greatest relative difference: 0.4378257691860199 at index (0, 0, 0, 32, 113) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_fft_nufft[2d_cartesian_irregular_sampling] AssertionError: Tensor-likes are not close! Mismatched elements: 192 / 192 (100.0%) Greatest absolute difference: 0.09371276199817657 at index (0, 0, 0, 0, 133) (up to 1e-05 allowed) Greatest relative difference: 0.1566677689552307 at index (0, 0, 0, 0, 140) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py311)

test_fourier_op_fft_nufft[2d_cartesian_cine_9_cardiac_phases_6_coils] AssertionError: Tensor-likes are not close! Mismatched elements: 1327104 / 1327104 (100.0%) Greatest absolute difference: 0.47035491466522217 at index (4, 5, 0, 48, 3) (up to 1e-05 allowed) Greatest relative difference: 0.6732349991798401 at index (3, 0, 0, 96, 35) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_fft_nufft[2d_cartesian_1_coil_no_oversampling] AssertionError: Tensor-likes are not close! Mismatched elements: 12288 / 12288 (100.0%) Greatest absolute difference: 0.9110996127128601 at index (0, 0, 0, 70, 56) (up to 1e-05 allowed) Greatest relative difference: 1.0034971237182617 at index (0, 0, 0, 65, 81) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_fft_nufft[2d_cartesian_1_coil_with_oversampling] AssertionError: Tensor-likes are not close! Mismatched elements: 24576 / 24576 (100.0%) Greatest absolute difference: 0.3774434030056 at index (0, 0, 0, 93, 84) (up to 1e-05 allowed) Greatest relative difference: 0.4378257691860199 at index (0, 0, 0, 32, 113) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_fft_nufft[2d_cartesian_irregular_sampling] AssertionError: Tensor-likes are not close! Mismatched elements: 192 / 192 (100.0%) Greatest absolute difference: 0.09371276199817657 at index (0, 0, 0, 0, 133) (up to 1e-05 allowed) Greatest relative difference: 0.1566677689552307 at index (0, 0, 0, 0, 140) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py312)

test_fourier_op_fft_nufft[2d_cartesian_cine_9_cardiac_phases_6_coils] AssertionError: Tensor-likes are not close! Mismatched elements: 1327104 / 1327104 (100.0%) Greatest absolute difference: 0.47035491466522217 at index (4, 5, 0, 48, 3) (up to 1e-05 allowed) Greatest relative difference: 0.6732349991798401 at index (3, 0, 0, 96, 35) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_fft_nufft[2d_cartesian_1_coil_no_oversampling] AssertionError: Tensor-likes are not close! Mismatched elements: 12288 / 12288 (100.0%) Greatest absolute difference: 0.9110996127128601 at index (0, 0, 0, 70, 56) (up to 1e-05 allowed) Greatest relative difference: 1.0034971237182617 at index (0, 0, 0, 65, 81) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_fft_nufft[2d_cartesian_1_coil_with_oversampling] AssertionError: Tensor-likes are not close! Mismatched elements: 24576 / 24576 (100.0%) Greatest absolute difference: 0.3774434030056 at index (0, 0, 0, 93, 84) (up to 1e-05 allowed) Greatest relative difference: 0.4378257691860199 at index (0, 0, 0, 32, 113) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_fft_nufft[2d_cartesian_irregular_sampling] AssertionError: Tensor-likes are not close! Mismatched elements: 192 / 192 (100.0%) Greatest absolute difference: 0.09371276199817657 at index (0, 0, 0, 0, 133) (up to 1e-05 allowed) Greatest relative difference: 0.1566677689552307 at index (0, 0, 0, 0, 140) (up to 0.0001 allowed)

Check failure on line 107 in tests/operators/test_fourier_op.py

View workflow job for this annotation

GitHub Actions / Run Tests and Coverage Report (mrpro_py310)

test_fourier_op_fft_nufft[2d_cartesian_cine_9_cardiac_phases_6_coils] AssertionError: Tensor-likes are not close! Mismatched elements: 1327104 / 1327104 (100.0%) Greatest absolute difference: 0.47035491466522217 at index (4, 5, 0, 48, 3) (up to 1e-05 allowed) Greatest relative difference: 0.6732349991798401 at index (3, 0, 0, 96, 35) (up to 0.0001 allowed)

k = RandomGenerator(0).complex64_tensor(size=k_shape)
(result_normal,) = fourier_op.H(k)
(result_nufft,) = nufft_fourier_op.H(k)
torch.testing.assert_close(result_normal, result_nufft, atol=1e-5, rtol=1e-4)

(result_normal,) = fourier_op(img)
(result_nufft,) = nufft_fourier_op(img)
torch.testing.assert_close(result_normal, result_nufft, atol=1e-5, rtol=1e-4)


@COMMON_MR_TRAJECTORIES
def test_fourier_op_gram(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz, type_k0, type_k1, type_k2):
"""Test gram of Fourier operator."""
Expand Down

0 comments on commit 5c29809

Please sign in to comment.