diff --git a/MRIBase/Project.toml b/MRIBase/Project.toml index 71d595f0..c84ae80c 100644 --- a/MRIBase/Project.toml +++ b/MRIBase/Project.toml @@ -15,7 +15,8 @@ NFFTTools = "0.2.4" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" [targets] -test = ["Test"] +test = ["Test", "Random"] diff --git a/MRIBase/test/Utils.jl b/MRIBase/test/Utils.jl new file mode 100644 index 00000000..b5ddeffd --- /dev/null +++ b/MRIBase/test/Utils.jl @@ -0,0 +1,82 @@ +module Utils +using MRIBase + +export get_default_cartesian_raw_acq_data + +function get_default_cartesian_raw_acq_data_2d(n_profiles, n_samples_per_profile, data = nothing) + params = Dict{String, Any}() + params["trajectory"] = "Cartesian" + params["encodedSize"] = [n_samples_per_profile, n_profiles] + params["encodedFOV"] = [n_samples_per_profile, n_profiles, 1] + + traj_nodes = kspaceNodes(trajectory(Float32, "Cartesian", n_profiles, n_samples_per_profile)) + traj_nodes = reshape(traj_nodes, 2, n_samples_per_profile, n_profiles) + if data == nothing + data = rand(ComplexF32, n_samples_per_profile, n_profiles) + end + + profiles = Vector{Profile}(undef, n_profiles) + for i_profile in 1:n_profiles + profile_head = AcquisitionHeader(idx = EncodingCounters(kspace_encode_step_1 = i_profile - 1), center_sample = div(n_samples_per_profile, 2)) + profiles[i_profile] = Profile( + profile_head, + traj_nodes[:, :, i_profile], + reshape(data[:, i_profile], n_samples_per_profile, 1), + ) + end + + f = RawAcquisitionData( + params, + profiles, + ) + return f +end + + +function get_default_cartesian_raw_acq_data_3d(n_slices, n_profiles, n_samples_per_profile, data = nothing, mask=nothing) + params = Dict{String, Any}() + params["trajectory"] = "Cartesian" + params["encodedSize"] = [n_samples_per_profile, n_profiles, n_slices] + params["encodedFOV"] = [n_samples_per_profile, n_profiles, n_slices] + + traj_nodes = kspaceNodes(trajectory(Float32, "Cartesian3D", n_profiles, n_samples_per_profile, numSlices=n_slices)) + traj_nodes = reshape(traj_nodes, 3, n_samples_per_profile, n_profiles, n_slices) + if data == nothing + data = rand(ComplexF32, n_samples_per_profile, n_profiles, n_slices) + end + + n_elemens = mask == nothing ? n_profiles*n_slices : sum(mask) + profiles = Vector{Profile}(undef, n_elemens) + i = 1 + for i_profile in 1:n_profiles + for i_slice in 1:n_slices + if mask != nothing && !mask[1, i_profile, i_slice] + continue + end + + profile_head = AcquisitionHeader( + idx = EncodingCounters( + kspace_encode_step_1 = i_profile - 1, + kspace_encode_step_2 = i_slice - 1, + ), + center_sample = div(n_samples_per_profile, 2), + trajectory_dimensions=3, + ) + # profiles[(i_slice-1)*n_profiles+i_profile] = Profile( + profiles[i] = Profile( + profile_head, + traj_nodes[:, :, i_profile, i_slice], + reshape(data[:, i_profile, i_slice], n_samples_per_profile, 1), + ) + i += 1 + end + end + + f = RawAcquisitionData( + params, + profiles, + ) + return f +end + +end diff --git a/MRIBase/test/runtests.jl b/MRIBase/test/runtests.jl index 49a100f4..3b4a9668 100644 --- a/MRIBase/test/runtests.jl +++ b/MRIBase/test/runtests.jl @@ -1,5 +1,9 @@ using Test, MRIBase +include("Utils.jl") + include("testTrajectories.jl") include("testFlags.jl") -include("testConversion.jl") \ No newline at end of file +include("testRawAcqData.jl") +include("testAcqData.jl") +include("testConversion.jl") diff --git a/MRIBase/test/testAcqData.jl b/MRIBase/test/testAcqData.jl new file mode 100644 index 00000000..198e47fc --- /dev/null +++ b/MRIBase/test/testAcqData.jl @@ -0,0 +1,34 @@ +using .Utils: get_default_cartesian_raw_acq_data_2d, get_default_cartesian_raw_acq_data_3d + + +@testset "kDataCart restores the order when profiles are shuffled" begin + n_profiles = 10 + n_samples_per_profile = 12 + data = rand(ComplexF32, n_samples_per_profile, n_profiles) + f = get_default_cartesian_raw_acq_data_2d(n_profiles, n_samples_per_profile, data) + f.profiles = shuffle(f.profiles) + acq = AcquisitionData(f) + kdata = kDataCart(acq)[:, :, 1, 1, 1, 1] + @test isapprox(kdata, data) +end + + +@testset "kDataCart restores the order when profiles are shuffled for 3D data" begin + n_profiles = 10 + n_samples_per_profile = 12 + n_slices = 3 + data = rand(ComplexF32, n_samples_per_profile, n_profiles, n_slices) + elipsoid_mask = zeros(Bool, 1, n_profiles, n_slices) + for i in 1:n_profiles + for j in 1:n_slices + elipsoid_mask[1, i, j] = (i-5)^2/25 + (j-2)^2/4 < 0.5 + end + end + data .*= elipsoid_mask + f = get_default_cartesian_raw_acq_data_3d(n_slices, n_profiles, n_samples_per_profile, data, elipsoid_mask) + f.profiles = shuffle(f.profiles) + acq = AcquisitionData(f) + kdata = kDataCart(acq)[:, :, :, 1, 1, 1] + + @test isapprox(kdata, data) +end diff --git a/MRIBase/test/testRawAcqData.jl b/MRIBase/test/testRawAcqData.jl new file mode 100644 index 00000000..783ec9b2 --- /dev/null +++ b/MRIBase/test/testRawAcqData.jl @@ -0,0 +1,26 @@ +using Random +using MRIBase +using .Utils: get_default_cartesian_raw_acq_data_2d + + +@testset "MRIBase.rawdata with dense 2D cartesian data" begin + n_profiles = 10 + n_samples_per_profile = 12 + data = rand(ComplexF32, n_samples_per_profile, n_profiles) + f = get_default_cartesian_raw_acq_data_2d(n_profiles, n_samples_per_profile, data) + kdata = MRIBase.rawdata(f) + kdata = reshape(kdata, n_samples_per_profile, n_profiles) + @test isapprox(kdata, data) +end + + +@testset "MRIBase.rawdata is not supposed to handle shuffles profiles" begin + n_profiles = 10 + n_samples_per_profile = 12 + data = rand(ComplexF32, n_samples_per_profile, n_profiles) + f = get_default_cartesian_raw_acq_data_2d(n_profiles, n_samples_per_profile, data) + shuffle!(f.profiles) + kdata = MRIBase.rawdata(f) + kdata = reshape(kdata, n_samples_per_profile, n_profiles) + @test !isapprox(kdata, data) +end