Skip to content

Commit 0b6d9ed

Browse files
authored
Merge pull request #80 from MagneticResonanceImaging/bugfix_cmaps
Fix incorrect trj indexing for low-res recon in calculate_coil_maps
2 parents f396c54 + b182270 commit 0b6d9ed

7 files changed

Lines changed: 18 additions & 3 deletions

File tree

ext/MRISubspaceReconCUDAExt/BackProjection.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ end
8787
function MRISubspaceRecon.calculate_backprojection(data::CuArray{Tc}, trj::CuArray{<:Integer,3}, cmaps::AbstractVector{<:CuArray}; U=cu(I(size(trj)[end])), sample_mask=CUDA.ones(Bool, size(trj)[2:end])) where {Tc <: Complex}
8888
Ncoeff = size(U, 2)
8989
img_shape = size(cmaps[1])
90+
trj_cpu = Array(trj)
91+
mask_cpu = Array(sample_mask)
92+
@assert all(d -> all((@view(trj_cpu[d, :, :])[mask_cpu]) .>= 1) && all((@view(trj_cpu[d, :, :])[mask_cpu]) .<= img_shape[d]), 1:size(trj, 1)) "Cartesian trajectory values must be in the range 1:img_shape[d] for each dimension d."
9093
img_idx = CartesianIndices(img_shape)
9194
T = real(eltype(data))
9295

@@ -119,6 +122,9 @@ function MRISubspaceRecon.calculate_backprojection(data::CuArray{Tc}, trj::CuArr
119122
end
120123

121124
function MRISubspaceRecon.calculate_backprojection(data::CuArray{Tc}, trj::CuArray{<:Integer,3}, img_shape; U=cu(I(size(trj)[end])), sample_mask=CUDA.ones(Bool, size(trj)[2:end])) where {Tc <: Complex}
125+
trj_cpu = Array(trj)
126+
mask_cpu = Array(sample_mask)
127+
@assert all(d -> all((@view(trj_cpu[d, :, :])[mask_cpu]) .>= 1) && all((@view(trj_cpu[d, :, :])[mask_cpu]) .<= img_shape[d]), 1:size(trj, 1)) "Cartesian trajectory values must be in the range 1:img_shape[d] for each dimension d."
122128
Ncoeff = size(U, 2)
123129
Ncoil = size(data, 3)
124130
img_idx = CartesianIndices(img_shape)

ext/MRISubspaceReconCUDAExt/CoilMaps.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ function MRISubspaceRecon.calculate_coil_maps(
7171
mask_calib .&= Array(sample_mask)
7272
mask_calib = cu(mask_calib)
7373

74-
x = MRISubspaceRecon.reconstruct_coilwise(data, trj, calib_size; U, sample_mask=mask_calib, Niter_cg)
74+
# Shift trajectory to 1:calib_size range for reconstruction on the calib grid
75+
trj_calib = CuArray{Int16}(trj .- lower_bound)
76+
x = MRISubspaceRecon.reconstruct_coilwise(data, trj_calib, calib_size; U, sample_mask=mask_calib, Niter_cg)
7577

7678
imdims = ntuple(i -> i, length(img_shape))
7779
kbp = fftshift(x, imdims)

ext/MRISubspaceReconCUDAExt/FFTNormalOp.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ end
5959
#############################################################################
6060

6161
function calculate_kernel_cartesian(img_shape, trj::CuArray{<:Integer,3}, U; sample_mask=CUDA.ones(Bool, size(trj)[2:end]), verbose=false)
62+
trj_cpu = Array(trj)
63+
mask_cpu = Array(sample_mask)
64+
@assert all(d -> all((@view(trj_cpu[d, :, :])[mask_cpu]) .>= 1) && all((@view(trj_cpu[d, :, :])[mask_cpu]) .<= img_shape[d]), 1:size(trj, 1)) "Cartesian trajectory values must be in the range 1:img_shape[d] for each dimension d."
6265
Ncoeff = size(U, 2)
6366
Nrep = size(U, 3) # number of repetitions (defaults to 1)
6467

ext/MRISubspaceReconCUDAExt/NFFTNormalOp.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ function calculate_kernel_noncartesian(img_shape_os, trj::CuArray{T,3}, U::CuArr
112112
# Configure threads and blocks for each kernel within the coefficient loop
113113
threads_multiply, blocks_multiply, threads_store, blocks_store = launch_config_kernel(nsamp_t, kmask_indcs)
114114

115-
116115
verbose && println("calculating non-Cartesian kernel...")
117116
t = @elapsed CUDA.@sync for ic2 1:Ncoeff, ic1 1:Ncoeff
118117
if ic2 >= ic1 # eval. only upper triangular matrix

src/BackProjection.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ end
106106
function calculate_backprojection(data::AbstractArray{Tc}, trj::AbstractArray{<:Integer,3}, cmaps::AbstractVector{<:AbstractArray}; U=I(size(trj)[end]), sample_mask=trues(size(trj)[2:end])) where {Tc <: Complex}
107107
Ncoeff = size(U, 2)
108108
img_shape = size(cmaps[1])
109+
@assert all(d -> all((@view(trj[d, :, :])[sample_mask]) .>= 1) && all((@view(trj[d, :, :])[sample_mask]) .<= img_shape[d]), 1:size(trj, 1)) "Cartesian trajectory values must be in the range 1:img_shape[d] for each dimension d."
109110
img_idx = CartesianIndices(img_shape)
110111

111112
dataU = similar(data, img_shape..., Ncoeff)
@@ -131,6 +132,7 @@ function calculate_backprojection(data::AbstractArray{Tc}, trj::AbstractArray{<:
131132
end
132133

133134
function calculate_backprojection(data::AbstractArray{Tc}, trj::AbstractArray{<:Integer,3}, img_shape; U=I(size(trj)[end]), sample_mask=trues(size(trj)[2:end])) where {Tc <: Complex}
135+
@assert all(d -> all((@view(trj[d, :, :])[sample_mask]) .>= 1) && all((@view(trj[d, :, :])[sample_mask]) .<= img_shape[d]), 1:size(trj, 1)) "Cartesian trajectory values must be in the range 1:img_shape[d] for each dimension d."
134136
Ncoeff = size(U, 2)
135137
Ncoil = size(data, 3)
136138
img_idx = CartesianIndices(img_shape)

src/CoilMaps.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ function calculate_coil_maps(
8080
mask_calib = dropdims(all(trj .> lower_bound; dims=1) .& all(trj .< upper_bound; dims=1); dims=1)
8181
mask_calib .&= sample_mask
8282

83-
x = reconstruct_coilwise(data, trj, calib_size; U, sample_mask=mask_calib, Niter_cg)
83+
# Shift trajectory to 1:calib_size range for reconstruction on the calib grid
84+
trj_calib = Int16.(trj .- lower_bound)
85+
x = reconstruct_coilwise(data, trj_calib, calib_size; U, sample_mask=mask_calib, Niter_cg)
8486

8587
imdims = ntuple(i -> i, length(img_shape))
8688
kbp = fftshift(x, imdims)

src/FFTNormalOp.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct _FFTNormalOp{S,E,F,G,H,I,J,K,L,M}
8888
end
8989

9090
function calculate_kernel_cartesian(img_shape, trj::AbstractArray{<:Integer,3}, U; sample_mask=trues(size(trj)[2:end]), verbose=false)
91+
@assert all(d -> all((@view(trj[d, :, :])[sample_mask]) .>= 1) && all((@view(trj[d, :, :])[sample_mask]) .<= img_shape[d]), 1:size(trj, 1)) "Cartesian trajectory values must be in the range 1:img_shape[d] for each dimension d."
9192
Ncoeff = size(U, 2)
9293
Λ = zeros(eltype(U), Ncoeff, Ncoeff, img_shape...)
9394

0 commit comments

Comments
 (0)