From bbdb42886100935e57a1baadec80eefb4f4f362c Mon Sep 17 00:00:00 2001 From: Felix Zimmermann Date: Sun, 27 Oct 2024 14:23:47 +0100 Subject: [PATCH 1/4] add parameterize ids --- tests/algorithms/test_cg.py | 3 +- tests/conftest.py | 294 +++++++++--------- tests/data/test_rotation.py | 8 +- tests/operators/functionals/conftest.py | 6 +- tests/operators/models/conftest.py | 20 +- tests/operators/test_cartesian_sampling_op.py | 12 +- tests/operators/test_fourier_op.py | 22 +- tests/operators/test_rearrangeop.py | 1 + 8 files changed, 194 insertions(+), 172 deletions(-) diff --git a/tests/algorithms/test_cg.py b/tests/algorithms/test_cg.py index 16c16e78b..ab705f114 100644 --- a/tests/algorithms/test_cg.py +++ b/tests/algorithms/test_cg.py @@ -16,7 +16,8 @@ (1, 32, False), (4, 32, True), (4, 32, False), - ] + ], + ids=['complex_single', 'real_single', 'complex_batch', 'real_batch'], ) def system(request): """Generate data for creating a system Hx=b with linear and self-adjoint diff --git a/tests/conftest.py b/tests/conftest.py index e3f943462..ce15c1ab8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -238,11 +238,11 @@ def create_traj(k_shape, nkx, nky, nkz, sx, sy, sz): random_generator = RandomGenerator(seed=0) k_list = [] for spacing, nk in zip([sz, sy, sx], [nkz, nky, nkx], strict=True): - if spacing == 'nuf': + if spacing == 'non-uniform': k = random_generator.float32_tensor(size=nk) - elif spacing == 'uf': + elif spacing == 'uniform': k = create_uniform_traj(nk, k_shape=k_shape) - elif spacing == 'z': + elif spacing == 'zero': k = torch.zeros(nk) k_list.append(k) trajectory = KTrajectory(k_list[0], k_list[1], k_list[2], repeat_detection_tolerance=None) @@ -252,159 +252,161 @@ def create_traj(k_shape, nkx, nky, nkz, sx, sy, sz): COMMON_MR_TRAJECTORIES = pytest.mark.parametrize( ('im_shape', 'k_shape', 'nkx', 'nky', 'nkz', 'sx', 'sy', 'sz', 's0', 's1', 's2'), [ - # (0) 2d cart mri with 1 coil, no oversampling - ( - (1, 1, 1, 96, 128), # img shape - (1, 1, 1, 96, 128), # k shape - (1, 1, 1, 128), # kx - (1, 1, 96, 1), # ky - (1, 1, 1, 1), # kz - 'uf', # kx is uniform - 'uf', # ky is uniform - 'z', # zero so no Fourier transform is performed along that dimension - 'uf', # k0 is uniform - 'uf', # k1 is uniform - 'z', # k2 is singleton + ( # (0) 2d cart mri with 1 coil, no oversampling + (1, 1, 1, 96, 128), # im_shape + (1, 1, 1, 96, 128), # k_shape + (1, 1, 1, 128), # nkx + (1, 1, 96, 1), # nky + (1, 1, 1, 1), # nkz + 'uniform', # sx + 'uniform', # sy + 'zero', # sz + 'uniform', # s0 + 'uniform', # s1 + 'zero', # s2 ), - # (1) 2d cart mri with 1 coil, with oversampling - ( - (1, 1, 1, 96, 128), - (1, 1, 1, 128, 192), - (1, 1, 1, 192), - (1, 1, 128, 1), - (1, 1, 1, 1), - 'uf', - 'uf', - 'z', - 'uf', - 'uf', - 'z', + ( # (1) 2d cart mri with 1 coil, with oversampling + (1, 1, 1, 96, 128), # im_shape + (1, 1, 1, 128, 192), # k_shape + (1, 1, 1, 192), # nkx + (1, 1, 128, 1), # nky + (1, 1, 1, 1), # nkz + 'uniform', # sx + 'uniform', # sy + 'zero', # sz + 'uniform', # s0 + 'uniform', # s1 + 'zero', # s2 ), - # (2) 2d non-Cartesian mri with 2 coils - ( - (1, 2, 1, 96, 128), - (1, 2, 1, 16, 192), - (1, 1, 16, 192), - (1, 1, 16, 192), - (1, 1, 1, 1), - 'nuf', # kx is non-uniform - 'nuf', - 'z', - 'nuf', - 'nuf', - 'z', + ( # (2) 2d non-Cartesian mri with 2 coils + (1, 2, 1, 96, 128), # im_shape + (1, 2, 1, 16, 192), # k_shape + (1, 1, 16, 192), # nkx + (1, 1, 16, 192), # nky + (1, 1, 1, 1), # nkz + 'non-uniform', # sx + 'non-uniform', # sy + 'zero', # sz + 'non-uniform', # s0 + 'non-uniform', # s1 + 'zero', # s2 ), - # (3) 2d cart mri with irregular sampling - ( - (1, 1, 1, 96, 128), - (1, 1, 1, 1, 192), - (1, 1, 1, 192), - (1, 1, 1, 192), - (1, 1, 1, 1), - 'uf', - 'uf', - 'z', - 'uf', - 'z', - 'z', + ( # (3) 2d cart mri with irregular sampling + (1, 1, 1, 96, 128), # im_shape + (1, 1, 1, 1, 192), # k_shape + (1, 1, 1, 192), # nkx + (1, 1, 1, 192), # nky + (1, 1, 1, 1), # nkz + 'uniform', # sx + 'uniform', # sy + 'zero', # sz + 'uniform', # s0 + 'zero', # s1 + 'zero', # s2 ), - # (4) 2d single shot spiral - ( - (1, 2, 1, 96, 128), - (1, 1, 1, 1, 192), - (1, 1, 1, 192), - (1, 1, 1, 192), - (1, 1, 1, 1), - 'nuf', - 'nuf', - 'z', - 'nuf', - 'z', - 'z', + ( # (4) 2d single shot spiral + (1, 2, 1, 96, 128), # im_shape + (1, 1, 1, 1, 192), # k_shape + (1, 1, 1, 192), # nkx + (1, 1, 1, 192), # nky + (1, 1, 1, 1), # nkz + 'non-uniform', # sx + 'non-uniform', # sy + 'zero', # sz + 'non-uniform', # s0 + 'zero', # s1 + 'zero', # s2 ), - # (5) 3d nuFFT mri, 4 coils, 2 other - ( - (2, 4, 16, 32, 64), - (2, 4, 16, 32, 64), - (2, 16, 32, 64), - (2, 16, 32, 64), - (2, 16, 32, 64), - 'nuf', - 'nuf', - 'nuf', - 'nuf', - 'nuf', - 'nuf', + ( # (5) 3d nuniformFT mri, 4 coils, 2 other + (2, 4, 16, 32, 64), # im_shape + (2, 4, 16, 32, 64), # k_shape + (2, 16, 32, 64), # nkx + (2, 16, 32, 64), # nky + (2, 16, 32, 64), # nkz + 'non-uniform', # sx + 'non-uniform', # sy + 'non-uniform', # sz + 'non-uniform', # s0 + 'non-uniform', # s1 + 'non-uniform', # s2 ), - # (6) 2d nuFFT cine mri with 8 cardiac phases, 5 coils - ( - (8, 5, 1, 64, 64), - (8, 5, 1, 18, 128), - (8, 1, 18, 128), - (8, 1, 18, 128), - (8, 1, 1, 1), - 'nuf', - 'nuf', - 'z', - 'nuf', - 'nuf', - 'z', + ( # (6) 2d nuniformFT cine mri with 8 cardiac phases, 5 coils + (8, 5, 1, 64, 64), # im_shape + (8, 5, 1, 18, 128), # k_shape + (8, 1, 18, 128), # nkx + (8, 1, 18, 128), # nky + (8, 1, 1, 1), # nkz + 'non-uniform', # sx + 'non-uniform', # sy + 'zero', # sz + 'non-uniform', # s0 + 'non-uniform', # s1 + 'zero', # s2 ), - # (7) 2d cart cine mri with 9 cardiac phases, 6 coils - ( - (9, 6, 1, 96, 128), - (9, 6, 1, 128, 192), - (9, 1, 1, 192), - (9, 1, 128, 1), - (9, 1, 1, 1), - 'uf', - 'uf', - 'z', - 'uf', - 'uf', - 'z', + ( # (7) 2d cart cine mri with 9 cardiac phases, 6 coils + (9, 6, 1, 96, 128), # im_shape + (9, 6, 1, 128, 192), # k_shape + (9, 1, 1, 192), # nkx + (9, 1, 128, 1), # nky + (9, 1, 1, 1), # nkz + 'uniform', # sx + 'uniform', # sy + 'zero', # sz + 'uniform', # s0 + 'uniform', # s1 + 'zero', # s2 ), - # (8) radial phase encoding (RPE), 8 coils, with oversampling in both FFT and nuFFT directions - ( - (2, 8, 64, 32, 48), - (2, 8, 8, 64, 96), - (2, 1, 1, 96), - (2, 8, 64, 1), - (2, 8, 64, 1), - 'uf', - 'nuf', - 'nuf', - 'uf', - 'nuf', - 'nuf', + ( # (8) radial phase encoding (RPE), 8 coils, with oversampling in both FFT and nuniformFT directions + (2, 8, 64, 32, 48), # im_shape + (2, 8, 8, 64, 96), # k_shape + (2, 1, 1, 96), # nkx + (2, 8, 64, 1), # nky + (2, 8, 64, 1), # nkz + 'uniform', # sx + 'non-uniform', # sy + 'non-uniform', # sz + 'uniform', # s0 + 'non-uniform', # s1 + 'non-uniform', # s2 ), - # (9) radial phase encoding (RPE) , 8 coils with non-Cartesian sampling along readout - ( - (2, 8, 64, 32, 48), - (2, 8, 8, 64, 96), - (2, 1, 1, 96), - (2, 8, 64, 1), - (2, 8, 64, 1), - 'nuf', - 'nuf', - 'nuf', - 'nuf', - 'nuf', - 'nuf', + ( # (9) radial phase encoding (RPE) , 8 coils with non-Cartesian sampling along readout + (2, 8, 64, 32, 48), # im_shape + (2, 8, 8, 64, 96), # k_shape + (2, 1, 1, 96), # nkx + (2, 8, 64, 1), # nky + (2, 8, 64, 1), # nkz + 'non-uniform', # sx + 'non-uniform', # sy + 'non-uniform', # sz + 'non-uniform', # s0 + 'non-uniform', # s1 + 'non-uniform', # s2 ), - # (10) stack of stars, 5 other, 3 coil, oversampling in both FFT and nuFFT directions - ( - (5, 3, 48, 16, 32), - (5, 3, 96, 18, 64), - (5, 1, 18, 64), - (5, 1, 18, 64), - (5, 96, 1, 1), - 'nuf', - 'nuf', - 'uf', - 'nuf', - 'nuf', - 'uf', + ( # (10) stack of stars, 5 other, 3 coil, oversampling in both FFT and nuniformFT directions + (5, 3, 48, 16, 32), # im_shape + (5, 3, 96, 18, 64), # k_shape + (5, 1, 18, 64), # nkx + (5, 1, 18, 64), # nky + (5, 96, 1, 1), # nkz + 'non-uniform', # sx + 'non-uniform', # sy + 'uniform', # sz + 'non-uniform', # s0 + 'non-uniform', # s1 + 'uniform', # s2 ), ], + ids=[ + '2d_cart_mri_1_coil_no_oversampling', + '2d_cart_mri_1_coil_with_oversampling', + '2d_non_cartesian_mri_2_coils', + '2d_cart_mri_irregular_sampling', + '2d_single_shot_spiral', + '3d_nuniformFT_mri_4_coils_2_other', + '2d_nuniformFT_cine_mri_8_cardiac_phases_5_coils', + '2d_cart_cine_mri_9_cardiac_phases_6_coils', + 'radial_phase_encoding_8_coils_with_oversampling', + 'radial_phase_encoding_8_coils_non_cartesian_sampling', + 'stack_of_stars_5_other_3_coil_with_oversampling', + ], ) diff --git a/tests/data/test_rotation.py b/tests/data/test_rotation.py index 6b4cbb52c..035a2d6c6 100644 --- a/tests/data/test_rotation.py +++ b/tests/data/test_rotation.py @@ -535,7 +535,7 @@ def _test_stats(error: torch.Tensor, mean_max: float, rms_max: float) -> None: assert torch.all(rms < rms_max) -@pytest.mark.parametrize('seq_tuple', permutations('xyz')) +@pytest.mark.parametrize('seq_tuple', permutations('xyz'), ids=str) @pytest.mark.parametrize('intrinsic', [False, True]) def test_as_euler_asymmetric_axes(seq_tuple, intrinsic): rnd = RandomGenerator(0) @@ -555,7 +555,7 @@ def test_as_euler_asymmetric_axes(seq_tuple, intrinsic): _test_stats(angles_quat - angles, 1e-15, 1e-14) -@pytest.mark.parametrize('seq_tuple', permutations('xyz')) +@pytest.mark.parametrize('seq_tuple', permutations('xyz'), ids=str) @pytest.mark.parametrize('intrinsic', [False, True]) def test_as_euler_symmetric_axes(seq_tuple, intrinsic): rnd = RandomGenerator(0) @@ -576,7 +576,7 @@ def test_as_euler_symmetric_axes(seq_tuple, intrinsic): _test_stats(angles_quat - angles, 1e-16, 1e-14) -@pytest.mark.parametrize('seq_tuple', permutations('xyz')) +@pytest.mark.parametrize('seq_tuple', permutations('xyz'), ids=str) @pytest.mark.parametrize('intrinsic', [False, True]) def test_as_euler_degenerate_asymmetric_axes(seq_tuple, intrinsic): # Since we cannot check for angle equality, we check for rotation matrix @@ -598,7 +598,7 @@ def test_as_euler_degenerate_asymmetric_axes(seq_tuple, intrinsic): torch.testing.assert_close(mat_expected, mat_estimated) -@pytest.mark.parametrize('seq_tuple', permutations('xyz')) +@pytest.mark.parametrize('seq_tuple', permutations('xyz'), ids=str) @pytest.mark.parametrize('intrinsic', [False, True]) def test_as_euler_degenerate_symmetric_axes(seq_tuple, intrinsic): # Since we cannot check for angle equality, we check for rotation matrix diff --git a/tests/operators/functionals/conftest.py b/tests/operators/functionals/conftest.py index 9d2bfd8c9..ae8ffc20b 100644 --- a/tests/operators/functionals/conftest.py +++ b/tests/operators/functionals/conftest.py @@ -47,12 +47,12 @@ def result_dtype(self): def functional_test_cases(func: Callable[[FunctionalTestCase], None]) -> Callable[..., None]: """Decorator combining multiple parameterizations for test cases for all proximable functionals.""" - @pytest.mark.parametrize('shape', [[1, 2, 3]]) + @pytest.mark.parametrize('shape', [[1, 2, 3]], ids=['shape=[1,2,3]']) @pytest.mark.parametrize('dtype_name', ['float32', 'complex64']) @pytest.mark.parametrize('weight', ['scalar_weight', 'tensor_weight', 'complex_weight']) @pytest.mark.parametrize('target', ['no_target', 'random_target']) - @pytest.mark.parametrize('dim', [None]) - @pytest.mark.parametrize('divide_by_n', [True, False]) + @pytest.mark.parametrize('dim', [None], ids=['dim=None']) + @pytest.mark.parametrize('divide_by_n', [True, False], ids=['mean', 'sum']) @pytest.mark.parametrize('functional', PROXIMABLE_FUNCTIONALS) def wrapper( functional: type[ElementaryProximableFunctional], diff --git a/tests/operators/models/conftest.py b/tests/operators/models/conftest.py index 570fa2f1f..75fceacd2 100644 --- a/tests/operators/models/conftest.py +++ b/tests/operators/models/conftest.py @@ -8,7 +8,7 @@ SHAPE_VARIATIONS_SIGNAL_MODELS = pytest.mark.parametrize( ('parameter_shape', 'contrast_dim_shape', 'signal_shape'), [ - ((1, 1, 10, 20, 30), (5,), (5, 1, 1, 10, 20, 30)), # single map with different inversion times + ((1, 1, 10, 20, 30), (5,), (5, 1, 1, 10, 20, 30)), # single map with different contrast times ((1, 1, 10, 20, 30), (5, 1), (5, 1, 1, 10, 20, 30)), ((4, 1, 1, 10, 20, 30), (5, 1), (5, 4, 1, 1, 10, 20, 30)), # multiple maps along additional batch dimension ((4, 1, 1, 10, 20, 30), (5,), (5, 4, 1, 1, 10, 20, 30)), @@ -25,6 +25,24 @@ ((1,), (5,), (5, 1)), # single voxel ((4, 3, 1), (5, 4, 3), (5, 4, 3, 1)), ], + ids=[ + 'single_map_diff_contrast_times', + 'single_map_diff_contrast_times_2', + 'multiple_maps_additional_batch_dim', + 'multiple_maps_additional_batch_dim_2', + 'multiple_maps_additional_batch_dim_3', + 'multiple_maps_other_dim', + 'multiple_maps_other_dim_2', + 'multiple_maps_other_dim_3', + 'multiple_maps_other_and_batch_dim', + 'multiple_maps_other_and_batch_dim_2', + 'multiple_maps_other_and_batch_dim_3', + 'multiple_maps_other_and_batch_dim_4', + 'multiple_maps_other_and_batch_dim_5', + 'different_value_each_voxel', + 'single_voxel', + 'multiple_voxels', + ], ) diff --git a/tests/operators/test_cartesian_sampling_op.py b/tests/operators/test_cartesian_sampling_op.py index 6a1120e79..953def0e2 100644 --- a/tests/operators/test_cartesian_sampling_op.py +++ b/tests/operators/test_cartesian_sampling_op.py @@ -16,9 +16,9 @@ def test_cart_sampling_op_data_match(): nkx = (1, 1, 1, 60) nky = (1, 1, 40, 1) nkz = (1, 20, 1, 1) - sx = 'uf' - sy = 'uf' - sz = 'uf' + sx = 'uniform' + sy = 'uniform' + sz = 'uniform' trajectory = create_traj(k_shape, nkx, nky, nkz, sx, sy, sz) # Create matching data @@ -69,9 +69,9 @@ def test_cart_sampling_op_fwd_adj(sampling): nkx = (2, 1, 1, 60) nky = (2, 1, 40, 1) nkz = (2, 20, 1, 1) - sx = 'uf' - sy = 'uf' - sz = 'uf' + sx = 'uniform' + sy = 'uniform' + sz = 'uniform' trajectory_tensor = create_traj(k_shape, nkx, nky, nkz, sx, sy, sz).as_tensor() # Subsample data and trajectory diff --git a/tests/operators/test_fourier_op.py b/tests/operators/test_fourier_op.py index 89a4bbc11..42346fbb9 100644 --- a/tests/operators/test_fourier_op.py +++ b/tests/operators/test_fourier_op.py @@ -42,20 +42,20 @@ def test_fourier_fwd_adj_property(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz, @pytest.mark.parametrize( - ('im_shape', 'k_shape', 'nkx', 'nky', 'nkz', 'sx', 'sy', 'sz'), + ('im_shape', 'k_shape', 'nkx', 'nky', 'nkz', 'sx', 'sy', 'sz'), # parameter names [ - # Cartesian FFT dimensions are not aligned with corresponding k2, k1, k0 dimensions - ( - (5, 3, 48, 16, 32), - (5, 3, 96, 18, 64), - (5, 1, 18, 64), - (5, 96, 1, 1), # Cartesian ky dimension defined along k2 rather than k1 - (5, 1, 18, 64), - 'nuf', - 'uf', - 'nuf', + ( # Cartesian FFT dimensions are not aligned with corresponding k2, k1, k0 dimensions + (5, 3, 48, 16, 32), # im_shape + (5, 3, 96, 18, 64), # k_shape + (5, 1, 18, 64), # nkx + (5, 96, 1, 1), # nky - Cartesian ky dimension defined along k2 rather than k1 + (5, 1, 18, 64), # nkz + 'non-uniform', # sx + 'uniform', # sy + 'non-uniform', # sz ), ], + ids=['cartesian_fft_dims_not_aligned_with_k2_k1_k0_dims'], ) def test_fourier_not_supported_traj(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz): """Test trajectory not supported by Fourier operator.""" diff --git a/tests/operators/test_rearrangeop.py b/tests/operators/test_rearrangeop.py index 3db888897..054c99402 100644 --- a/tests/operators/test_rearrangeop.py +++ b/tests/operators/test_rearrangeop.py @@ -15,6 +15,7 @@ ((2, 2, 4), '... a b->... (a b)', (2, 8), {'b': 4}), # flatten ((2), '... (a b) -> ... a b', (2, 1), {'b': 1}), # unflatten ], + ids=['swap_axes', 'flatten', 'unflatten'], ) def test_einsum_op(input_shape, rule, output_shape, additional_info, dtype): """Test adjointness and shape.""" From cf2265f842216ab7884d46c50146bcc7954c469a Mon Sep 17 00:00:00 2001 From: Felix Zimmermann Date: Sat, 9 Nov 2024 13:00:54 +0100 Subject: [PATCH 2/4] review --- tests/conftest.py | 168 +++++++++--------- tests/data/test_trajectory.py | 20 +-- tests/operators/test_cartesian_sampling_op.py | 8 +- tests/operators/test_fourier_op.py | 22 +-- 4 files changed, 110 insertions(+), 108 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index ce15c1ab8..c358ddf14 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -233,11 +233,11 @@ def create_uniform_traj(nk, k_shape): return k -def create_traj(k_shape, nkx, nky, nkz, sx, sy, sz): +def create_traj(k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz): """Create trajectory with random entries.""" random_generator = RandomGenerator(seed=0) k_list = [] - for spacing, nk in zip([sz, sy, sx], [nkz, nky, nkx], strict=True): + for spacing, nk in zip([type_kz, type_ky, type_kx], [nkz, nky, nkx], strict=True): if spacing == 'non-uniform': k = random_generator.float32_tensor(size=nk) elif spacing == 'uniform': @@ -250,33 +250,33 @@ def create_traj(k_shape, nkx, nky, nkz, sx, sy, sz): COMMON_MR_TRAJECTORIES = pytest.mark.parametrize( - ('im_shape', 'k_shape', 'nkx', 'nky', 'nkz', 'sx', 'sy', 'sz', 's0', 's1', 's2'), + ('im_shape', 'k_shape', 'nkx', 'nky', 'nkz', 'type_kx', 'type_ky', 'type_kz', 'type_k0', 'type_k1', 'type_k2'), [ - ( # (0) 2d cart mri with 1 coil, no oversampling + ( # (0) 2d Cartesian single coil, no oversampling (1, 1, 1, 96, 128), # im_shape (1, 1, 1, 96, 128), # k_shape (1, 1, 1, 128), # nkx (1, 1, 96, 1), # nky (1, 1, 1, 1), # nkz - 'uniform', # sx - 'uniform', # sy - 'zero', # sz - 'uniform', # s0 - 'uniform', # s1 - 'zero', # s2 + 'uniform', # type_kx + 'uniform', # type_ky + 'zero', # type_kz + 'uniform', # type_k0 + 'uniform', # type_k1 + 'zero', # type_k2 ), - ( # (1) 2d cart mri with 1 coil, with oversampling + ( # (1) 2d Cartesian single coil, with oversampling (1, 1, 1, 96, 128), # im_shape (1, 1, 1, 128, 192), # k_shape (1, 1, 1, 192), # nkx (1, 1, 128, 1), # nky (1, 1, 1, 1), # nkz - 'uniform', # sx - 'uniform', # sy - 'zero', # sz - 'uniform', # s0 - 'uniform', # s1 - 'zero', # s2 + 'uniform', # type_kx + 'uniform', # type_ky + 'zero', # type_kz + 'uniform', # type_k0 + 'uniform', # type_k1 + 'zero', # type_k2 ), ( # (2) 2d non-Cartesian mri with 2 coils (1, 2, 1, 96, 128), # im_shape @@ -284,25 +284,25 @@ def create_traj(k_shape, nkx, nky, nkz, sx, sy, sz): (1, 1, 16, 192), # nkx (1, 1, 16, 192), # nky (1, 1, 1, 1), # nkz - 'non-uniform', # sx - 'non-uniform', # sy - 'zero', # sz - 'non-uniform', # s0 - 'non-uniform', # s1 - 'zero', # s2 + 'non-uniform', # type_kx + 'non-uniform', # type_ky + 'zero', # type_kz + 'non-uniform', # type_k0 + 'non-uniform', # type_k1 + 'zero', # type_k2 ), - ( # (3) 2d cart mri with irregular sampling + ( # (3) 2d Cartesian with irregular sampling (1, 1, 1, 96, 128), # im_shape (1, 1, 1, 1, 192), # k_shape (1, 1, 1, 192), # nkx (1, 1, 1, 192), # nky (1, 1, 1, 1), # nkz - 'uniform', # sx - 'uniform', # sy - 'zero', # sz - 'uniform', # s0 - 'zero', # s1 - 'zero', # s2 + 'uniform', # type_kx + 'uniform', # type_ky + 'zero', # type_kz + 'uniform', # type_k0 + 'zero', # type_k1 + 'zero', # type_k2 ), ( # (4) 2d single shot spiral (1, 2, 1, 96, 128), # im_shape @@ -310,101 +310,101 @@ def create_traj(k_shape, nkx, nky, nkz, sx, sy, sz): (1, 1, 1, 192), # nkx (1, 1, 1, 192), # nky (1, 1, 1, 1), # nkz - 'non-uniform', # sx - 'non-uniform', # sy - 'zero', # sz - 'non-uniform', # s0 - 'zero', # s1 - 'zero', # s2 + 'non-uniform', # type_kx + 'non-uniform', # type_ky + 'zero', # type_kz + 'non-uniform', # type_k0 + 'zero', # type_k1 + 'zero', # type_k2 ), - ( # (5) 3d nuniformFT mri, 4 coils, 2 other + ( # (5) 3d non-uniform, 4 coils, 2 other (2, 4, 16, 32, 64), # im_shape (2, 4, 16, 32, 64), # k_shape (2, 16, 32, 64), # nkx (2, 16, 32, 64), # nky (2, 16, 32, 64), # nkz - 'non-uniform', # sx - 'non-uniform', # sy - 'non-uniform', # sz - 'non-uniform', # s0 - 'non-uniform', # s1 - 'non-uniform', # s2 + 'non-uniform', # type_kx + 'non-uniform', # type_ky + 'non-uniform', # type_kz + 'non-uniform', # type_k0 + 'non-uniform', # type_k1 + 'non-uniform', # type_k2 ), - ( # (6) 2d nuniformFT cine mri with 8 cardiac phases, 5 coils + ( # (6) 2d non-uniform cine with 8 cardiac phases, 5 coils (8, 5, 1, 64, 64), # im_shape (8, 5, 1, 18, 128), # k_shape (8, 1, 18, 128), # nkx (8, 1, 18, 128), # nky (8, 1, 1, 1), # nkz - 'non-uniform', # sx - 'non-uniform', # sy - 'zero', # sz - 'non-uniform', # s0 - 'non-uniform', # s1 - 'zero', # s2 + 'non-uniform', # type_kx + 'non-uniform', # type_ky + 'zero', # type_kz + 'non-uniform', # type_k0 + 'non-uniform', # type_k1 + 'zero', # type_k2 ), - ( # (7) 2d cart cine mri with 9 cardiac phases, 6 coils + ( # (7) 2d cartesian cine with 9 cardiac phases, 6 coils (9, 6, 1, 96, 128), # im_shape (9, 6, 1, 128, 192), # k_shape (9, 1, 1, 192), # nkx (9, 1, 128, 1), # nky (9, 1, 1, 1), # nkz - 'uniform', # sx - 'uniform', # sy - 'zero', # sz - 'uniform', # s0 - 'uniform', # s1 - 'zero', # s2 + 'uniform', # type_kx + 'uniform', # type_ky + 'zero', # type_kz + 'uniform', # type_k0 + 'uniform', # type_k1 + 'zero', # type_k2 ), - ( # (8) radial phase encoding (RPE), 8 coils, with oversampling in both FFT and nuniformFT directions + ( # (8) radial phase encoding (RPE), 8 coils, with oversampling in both FFT and non-uniform directions (2, 8, 64, 32, 48), # im_shape (2, 8, 8, 64, 96), # k_shape (2, 1, 1, 96), # nkx (2, 8, 64, 1), # nky (2, 8, 64, 1), # nkz - 'uniform', # sx - 'non-uniform', # sy - 'non-uniform', # sz - 'uniform', # s0 - 'non-uniform', # s1 - 'non-uniform', # s2 + 'uniform', # type_kx + 'non-uniform', # type_ky + 'non-uniform', # type_kz + 'uniform', # type_k0 + 'non-uniform', # type_k1 + 'non-uniform', # type_k2 ), - ( # (9) radial phase encoding (RPE) , 8 coils with non-Cartesian sampling along readout + ( # (9) radial phase encoding (RPE), 8 coils with non-Cartesian sampling along readout (2, 8, 64, 32, 48), # im_shape (2, 8, 8, 64, 96), # k_shape (2, 1, 1, 96), # nkx (2, 8, 64, 1), # nky (2, 8, 64, 1), # nkz - 'non-uniform', # sx - 'non-uniform', # sy - 'non-uniform', # sz - 'non-uniform', # s0 - 'non-uniform', # s1 - 'non-uniform', # s2 + 'non-uniform', # type_kx + 'non-uniform', # type_ky + 'non-uniform', # type_kz + 'non-uniform', # type_k0 + 'non-uniform', # type_k1 + 'non-uniform', # type_k2 ), - ( # (10) stack of stars, 5 other, 3 coil, oversampling in both FFT and nuniformFT directions + ( # (10) stack of stars, 5 other, 3 coil, oversampling in both FFT and non-uniform directions (5, 3, 48, 16, 32), # im_shape (5, 3, 96, 18, 64), # k_shape (5, 1, 18, 64), # nkx (5, 1, 18, 64), # nky (5, 96, 1, 1), # nkz - 'non-uniform', # sx - 'non-uniform', # sy - 'uniform', # sz - 'non-uniform', # s0 - 'non-uniform', # s1 - 'uniform', # s2 + 'non-uniform', # type_kx + 'non-uniform', # type_ky + 'uniform', # type_kz + 'non-uniform', # type_k0 + 'non-uniform', # type_k1 + 'uniform', # type_k2 ), ], ids=[ - '2d_cart_mri_1_coil_no_oversampling', - '2d_cart_mri_1_coil_with_oversampling', + '2d_cartesian_1_coil_no_oversampling', + '2d_cartesian_1_coil_with_oversampling', '2d_non_cartesian_mri_2_coils', - '2d_cart_mri_irregular_sampling', + '2d_cartesian_irregular_sampling', '2d_single_shot_spiral', - '3d_nuniformFT_mri_4_coils_2_other', - '2d_nuniformFT_cine_mri_8_cardiac_phases_5_coils', - '2d_cart_cine_mri_9_cardiac_phases_6_coils', + '3d_nonuniform_4_coils_2_other', + '2d_nnonuniform_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', 'stack_of_stars_5_other_3_coil_with_oversampling', diff --git a/tests/data/test_trajectory.py b/tests/data/test_trajectory.py index 1baf4340b..1061a93be 100644 --- a/tests/data/test_trajectory.py +++ b/tests/data/test_trajectory.py @@ -147,16 +147,16 @@ def test_trajectory_cpu(cartesian_grid): @COMMON_MR_TRAJECTORIES -def test_ktype_along_kzyx(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz, s0, s1, s2): +def test_ktype_along_kzyx(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz, type_k0, type_k1, type_k2): """Test identification of traj types.""" # Generate random k-space trajectories - trajectory = create_traj(k_shape, nkx, nky, nkz, sx, sy, sz) + trajectory = create_traj(k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz) # Find out the type of the kz, ky and kz dimensions - single_value_dims = [d for d, s in zip((-3, -2, -1), (sz, sy, sx), strict=True) if s == 'z'] - on_grid_dims = [d for d, s in zip((-3, -2, -1), (sz, sy, sx), strict=True) if s == 'uf'] - not_on_grid_dims = [d for d, s in zip((-3, -2, -1), (sz, sy, sx), strict=True) if s == 'nuf'] + single_value_dims = [d for d, s in zip((-3, -2, -1), (type_kz, type_ky, type_kx), strict=True) if s == 'z'] + on_grid_dims = [d for d, s in zip((-3, -2, -1), (type_kz, type_ky, type_kx), strict=True) if s == 'uf'] + not_on_grid_dims = [d for d, s in zip((-3, -2, -1), (type_kz, type_ky, type_kx), strict=True) if s == 'nuf'] # check dimensions which are of shape 1 and do not need any transform assert all(trajectory.type_along_kzyx[dim] & TrajType.SINGLEVALUE for dim in single_value_dims) @@ -171,16 +171,16 @@ def test_ktype_along_kzyx(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz, s0, s1, @COMMON_MR_TRAJECTORIES -def test_ktype_along_k210(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz, s0, s1, s2): +def test_ktype_along_k210(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz, type_k0, type_k1, type_k2): """Test identification of traj types.""" # Generate random k-space trajectories - trajectory = create_traj(k_shape, nkx, nky, nkz, sx, sy, sz) + trajectory = create_traj(k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz) # Find out the type of the k2, k1 and k0 dimensions - single_value_dims = [d for d, s in zip((-3, -2, -1), (s2, s1, s0), strict=True) if s == 'z'] - on_grid_dims = [d for d, s in zip((-3, -2, -1), (s2, s1, s0), strict=True) if s == 'uf'] - not_on_grid_dims = [d for d, s in zip((-3, -2, -1), (s2, s1, s0), strict=True) if s == 'nuf'] + single_value_dims = [d for d, s in zip((-3, -2, -1), (type_k2, type_k1, type_k0), strict=True) if s == 'z'] + on_grid_dims = [d for d, s in zip((-3, -2, -1), (type_k2, type_k1, type_k0), strict=True) if s == 'uf'] + not_on_grid_dims = [d for d, s in zip((-3, -2, -1), (type_k2, type_k1, type_k0), strict=True) if s == 'nuf'] # check dimensions which are of shape 1 and do not need any transform assert all(trajectory.type_along_k210[dim] & TrajType.SINGLEVALUE for dim in single_value_dims) diff --git a/tests/operators/test_cartesian_sampling_op.py b/tests/operators/test_cartesian_sampling_op.py index 953def0e2..e5015a96b 100644 --- a/tests/operators/test_cartesian_sampling_op.py +++ b/tests/operators/test_cartesian_sampling_op.py @@ -16,10 +16,10 @@ def test_cart_sampling_op_data_match(): nkx = (1, 1, 1, 60) nky = (1, 1, 40, 1) nkz = (1, 20, 1, 1) - sx = 'uniform' - sy = 'uniform' - sz = 'uniform' - trajectory = create_traj(k_shape, nkx, nky, nkz, sx, sy, sz) + type_kx = 'uniform' + type_ky = 'uniform' + type_kz = 'uniform' + trajectory = create_traj(k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz) # Create matching data random_generator = RandomGenerator(seed=0) diff --git a/tests/operators/test_fourier_op.py b/tests/operators/test_fourier_op.py index 42346fbb9..0b0c17fc6 100644 --- a/tests/operators/test_fourier_op.py +++ b/tests/operators/test_fourier_op.py @@ -9,22 +9,24 @@ from tests.helper import dotproduct_adjointness_test -def create_data(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz): +def create_data(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz): random_generator = RandomGenerator(seed=0) # generate random image img = random_generator.complex64_tensor(size=im_shape) # create random trajectories - trajectory = create_traj(k_shape, nkx, nky, nkz, sx, sy, sz) + trajectory = create_traj(k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz) return img, trajectory @COMMON_MR_TRAJECTORIES -def test_fourier_fwd_adj_property(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz, s0, s1, s2): +def test_fourier_fwd_adj_property( + im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz, type_k0, type_k1, type_k2 +): """Test adjoint property of Fourier operator.""" # generate random images and k-space trajectories - img, trajectory = create_data(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz) + 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]) @@ -42,7 +44,7 @@ def test_fourier_fwd_adj_property(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz, @pytest.mark.parametrize( - ('im_shape', 'k_shape', 'nkx', 'nky', 'nkz', 'sx', 'sy', 'sz'), # parameter names + ('im_shape', 'k_shape', 'nkx', 'nky', 'nkz', 'type_kx', 'type_ky', 'type_kz'), # parameter names [ ( # Cartesian FFT dimensions are not aligned with corresponding k2, k1, k0 dimensions (5, 3, 48, 16, 32), # im_shape @@ -50,18 +52,18 @@ def test_fourier_fwd_adj_property(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz, (5, 1, 18, 64), # nkx (5, 96, 1, 1), # nky - Cartesian ky dimension defined along k2 rather than k1 (5, 1, 18, 64), # nkz - 'non-uniform', # sx - 'uniform', # sy - 'non-uniform', # sz + 'non-uniform', # type_kx + 'uniform', # type_ky + 'non-uniform', # type_kz ), ], ids=['cartesian_fft_dims_not_aligned_with_k2_k1_k0_dims'], ) -def test_fourier_not_supported_traj(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz): +def test_fourier_not_supported_traj(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz): """Test trajectory not supported by Fourier operator.""" # generate random images and k-space trajectories - img, trajectory = create_data(im_shape, k_shape, nkx, nky, nkz, sx, sy, sz) + 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]) From 643a431b82ff232e06a9eb80c0a958c25695ea5a Mon Sep 17 00:00:00 2001 From: Felix Zimmermann Date: Sun, 10 Nov 2024 19:01:27 +0100 Subject: [PATCH 3/4] review --- tests/operators/test_cartesian_sampling_op.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/operators/test_cartesian_sampling_op.py b/tests/operators/test_cartesian_sampling_op.py index e5015a96b..97efd0ff8 100644 --- a/tests/operators/test_cartesian_sampling_op.py +++ b/tests/operators/test_cartesian_sampling_op.py @@ -69,10 +69,10 @@ def test_cart_sampling_op_fwd_adj(sampling): nkx = (2, 1, 1, 60) nky = (2, 1, 40, 1) nkz = (2, 20, 1, 1) - sx = 'uniform' - sy = 'uniform' - sz = 'uniform' - trajectory_tensor = create_traj(k_shape, nkx, nky, nkz, sx, sy, sz).as_tensor() + type_kx = 'uniform' + type_ky = 'uniform' + type_kz = 'uniform' + trajectory_tensor = create_traj(k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz).as_tensor() # Subsample data and trajectory match sampling: From 071b04905767b504e45053f9c43cf87c81a1a4be Mon Sep 17 00:00:00 2001 From: Felix Zimmermann Date: Mon, 11 Nov 2024 16:40:16 +0100 Subject: [PATCH 4/4] rename test --- tests/operators/test_fourier_op.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/operators/test_fourier_op.py b/tests/operators/test_fourier_op.py index 0b0c17fc6..6f8c377cf 100644 --- a/tests/operators/test_fourier_op.py +++ b/tests/operators/test_fourier_op.py @@ -20,7 +20,7 @@ def create_data(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz): @COMMON_MR_TRAJECTORIES -def test_fourier_fwd_adj_property( +def test_fourier_op_fwd_adj_property( im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz, type_k0, type_k1, type_k2 ): """Test adjoint property of Fourier operator.""" @@ -59,7 +59,7 @@ def test_fourier_fwd_adj_property( ], ids=['cartesian_fft_dims_not_aligned_with_k2_k1_k0_dims'], ) -def test_fourier_not_supported_traj(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz): +def test_fourier_op_not_supported_traj(im_shape, k_shape, nkx, nky, nkz, type_kx, type_ky, type_kz): """Test trajectory not supported by Fourier operator.""" # generate random images and k-space trajectories