Methods list
MRIFieldmaps.MRIFieldmaps
MRIFieldmaps.Echotime
MRIFieldmaps.RealU
MRIFieldmaps.b0init
MRIFieldmaps.b0map
MRIFieldmaps.b0map
MRIFieldmaps.b0model
MRIFieldmaps.b0scale
MRIFieldmaps.coil_combine
MRIFieldmaps.phasecontrast
MRIFieldmaps.spdiff
MRIFieldmaps.spdiff1
MRIFieldmaps.spdiff2
Methods usage
MRIFieldmaps.MRIFieldmaps
— ModuleMRIFieldmaps
Module MRIFieldmaps
exports methods for fieldmap estimation.
MRIFieldmaps.Echotime
— TypeEchotime{T} = Union{AbstractVector{<:T}, NTuple{N,<:T} where N}
The echo times can be a vector or a Tuple.
MRIFieldmaps.RealU
— TypeRealU
A data type that is just Number
but is to be thought of as Union{Real, Unitful}
without needing a dependence on the Unitful
package.
MRIFieldmaps.b0init
— Methodfinit = b0init(ydata, echotime; kwargs...)
Classic B0 field map estimation based on the phase difference of complex images at two different echo times. If sensitivity maps (smap
) are provided, complex coil combination is done first. This code works with images of arbitrary dimensions (2D, 3D, etc.), and with multiple coils.
In the usual case where echotime
has units of seconds, the returned B0 fieldmap will have units of Hz.
If df
is nonempty (which always holds for water-fat case), then perform discrete maximum-likelihood estimation using fdict
.
In
ydata (dims..., nc, ne)
ne
sets of complex images fornc ≥ 1
coilsechotime (ne)
vector ofne ≥ 2
echo times (only first 2 are used)
Options
smap (dims..., nc)
complex coil maps; defaultnothing
threshold
setfinit
values where|y1| < threshold * max(|y1|)
to the mean of the "good" values where|y1| ≥ threshold * max(|y1|)
. default:0.1
Options for water-fat case:
df
Δf values in water-fat imaging (def:[]
) units Hz, e.g.,[440]
at 3Trelamp
relative amplitudes in multi-species water-fat (def:[]
)fband
frequency bandwidth forfdict; default
floor(1 / minimum(echo time spacing))`nf
number of discrete frequencies to try; default1+floor(fband)
so ≈1Hz spacingfdict
"dictionary" of discrete frequency values to try; defaultLinRange(-1/2,1/2,nf) * fband
Out
finit
initial B0 fieldmap estimate in Hz
MRIFieldmaps.b0map
— Function(fhat, times, out) = b0map(ydata, echotime; kwargs...)
Field map estimation from multiple (ne ≥ 2
) echo-time images, using preconditioned nonlinear CG (NCG) with a monotonic line search. This code works with images of arbitrary dimensions (2D, 3D, etc.), and with multiple coils.
Caution: single coil data must be reshaped to size (dims..., 1, ne)
.
The cost function for the single-coil case is: cost(w) = ∑_{j=1}^{#voxel} ∑_{m=1}^ne ∑_{n=1}^ne |y_{mj} y_{nj}| wj (1 - cos(w_j * (t_m - t_n) + ∠y_{ni} - ∠y_{mj})) + R(w)
where t_n
denotes the echo time of the n
th scan and R(w) = 0.5 * | C * w |^2
is a quadratic roughness regularizer based on 1st-order or 2nd-order finite differences. See the documentation for the general multi-coil case.
The initial field map finit
and output fhat
are field maps in Hz, but internally the code works with ω = 2π f
(rad/s).
In
ydata (dims..., nc, ne)
ne
sets of complex images fornc ≥ 1
coilsechotime::Echotime (ne ≥ 2)
echo time offsets (in seconds)
Options
finit (dims)
initial fieldmap estimate (in Hz); default fromb0init()
smap (dims..., nc)
complex coil maps; defaultnothing
mask (dims...)
logical reconstruction mask; default:trues(size(finit))
ninner
# of inner iterations for monotonic line search default:3
inner iterationsb0init_args::NamedTuple = (;)
options forb0init
, such asthreshold
niter
# of outer iterations (def:30
)order
order of the finite-difference matrix (def:2
)l2b
log2
of regularization parameter (def:-6
)gamma_type
CG direction::PR
= Polak-Ribiere (default):FR
= Fletcher-Reeves
precon
Preconditioner::I
(nothing):diag
:chol
may require too much memory:ichol
(default)
reset
# of iterations before resetting direction (def:Inf
)df
Δf values in water-fat imaging (def:[0]
) units Hz, e.g.,[440]
at 3Trelamp
relative amplitudes in multi-peak water-fat (def:[1]
)lldl_args::NamedTuple
options forlldl
, default:(;memory=2)
track::Bool
iftrue
then track cost and save all iterations (def:false
)chat::Bool = true
#@info
updates each iterationchat_iter::Int = 10
# print progress report every few iterations.
Out
fhat
final fieldmap estimate in Hztimes (niter+1)
wall time for each iterationout::NamedTuple
that contains:(xw, xf) (dims)
water / fat images if!iszero(df)
finit (dims)
initial fieldmap
- if
track == true
thenout
also contains:costs (niter+1)
(nonconvex) cost for each iterationfhats (dims, niter+1)
fieldmap estimates every iteration
The algorithm is based on the paper: C Y Lin, J A Fessler, "Efficient Regularized Field Map Estimation in 3D MRI", IEEE TCI 2020 https://doi.org/10.1109/TCI.2020.3031082 https://arxiv.org/abs/2005.08661
Please cite that paper if you use this code.
MRIFieldmaps.b0map
— Methodb0map()
This version expects masked column-like inputs. For expert use only.
In
finit (np)
initial estimate in Hz (np
is # of pixels in mask)zdata (np, ne)
ne
sets of coil-combined measurementssos (np)
sum-of-squares of coil mapsechotime (ne)
vector ofne
echo time offsetsmask (N)
logical reconstruction mask
MRIFieldmaps.b0model
— Methodb0model(fmap, xw, echotime; kwargs...)
Compute complex images for B0 field mapping. This function is used mainly for simulation, and for code testing.
Model: images[j,c,l] = smap[j,c] exp(ı 2π fmap[j] t_l) exp(-relax[j] t_l) x[j,l]
where x[j,l] = xw[j] + xf[j] * sum_{p=0}^P α_p exp(ı 2π Δf_p t_l)
.
Field map estimation from multiple (ne ≥ 2
) echo-time images,
In
fmap (dims)
fieldmap (in Hz)xw (dims)
water magnetization componentechotime (ne)
vector orTuple
ofne
echo time offsets (in sec)
Options
smap (dims..., nc)
complex coil maps, defaultones(size(fmap)..., 1)
xw (dims)
fat magnetization component, defaultzeros(size(fmap))
df
Δf values in water-fat imaging (def:[0]
) units Hz, e.g.,[440]
at 3Trelamp
relative amplitudes in multi-peak water-fat (def:[1]
)relax (dims)
R2* relaxation in same units asfmap
, i.e., 1/s
Out
ydata (dims..., nc, ne)
ne
sets of complex images fornc
coils
MRIFieldmaps.b0scale
— Method(ydata, scalefactor) = b0scale(ydata, echotime; dmax)
Scale complex images ydata
to account for R2* effects and for magnitude variations using median(di)
where
ri = sum_j sum_k |y_{ij} y_{ik}|^2 (t_k - t_j)^2
di = ri / sum_k |y_{ik}|^2
Only values where di > dmax * maximum(di)
affect scalefactor
, so it is fine to pass unmasked images here.
This normalization simplifies regularization parameter selection for regularized B0 fieldmap estimation. See eqn (9) and (15) of Funai & Fessler, Oct. 2008, IEEE T-MI, https://doi.org/10.1109/TMI.2008.923956
In
ydata (dims..., ne)
scan images forne
different echo timesechotime (ne)
echo times (units of sec if fieldmap is in Hz)
Option
dmax::Real
threshold for relativedi
value (default0.1
)
Out
ydata (dims..., ne)
scaled scan imagesscalefactor = sqrt(median(rj))
MRIFieldmaps.coil_combine
— Methodzdata, sos = coil_combine(ydata [, smap])
For estimating a B0 field map from complete multi-coil image data, it suffices to first do complex coil combination, while tracking the sum-of-squares sos
for proper weighting. When sensitivity maps are provided, often sos
is all 1's and 0's.
Uses a phase contrast coil combination approach (reference below) when sensitivity maps are not provided.
In
ydata (dims..., nc, ne)
ne ≥ 1
sets of complex images fornc ≥ 1
coilssmap (dims..., nc)
complex coil maps (optional)
Out
zdata (dims..., ne)
complex coil combination:sum_c smap[c]' * ydata[c] ./ sos
orsum_c ydata[c,1]' * ydata[c] ./ sos
(ifsmap
not provided orisnothing(smap)
)sos (dims...)
sum-of-squares:sum_c |smap[c]|^2
orsqrt.(sum_c |ydata[c,1]|^2
(ifsmap
not provided orisnothing(smap)
)
See equation [13] in M A Bernstein et al., "Reconstructions of Phase Contrast, Phased Array Multicoil Data", MRM 1994. https://doi.org/10.1002/mrm.1910320308
MRIFieldmaps.phasecontrast
— Methodpc = phasecontrast(ydata)
fhat = phasecontrast(ydata, echotime)
Compute the phase contrast between two multicoil data sets. If echotime
is provided, return a field map by converting from radians to Hz (if echotime
is in seconds, as is typical).
In
ydata (dims..., nc, ne)
ne
sets of complex images fornc ≥ 1
coilsechotime::Echotime (ne = 2)
echo time offsets
Out
pc (dims...)
phase contrast (or field map, ifechotime
is provided):∠(sum_c ydata[c,1]' * ydata[c,2])
See equation [13] in M A Bernstein et al., "Reconstructions of Phase Contrast, Phased Array Multicoil Data", MRM 1994. https://doi.org/10.1002/mrm.1910320308
MRIFieldmaps.spdiff
— Methodspdiff(dims::Dims; order=1, kwargs...)
Return Vector
of length(dims)
sparse finite-difference matrices of order order
, one for each dimension.
Typically one will vcat
the vector output to make a sparse finite-difference matrix suitable for the vec
of a multi-dimensional array.
The kwargs
are passed to spdiff1
(for order = 1
) or spdiff2
(for order = 2
). These functions are called once for each dimension. The options are ending
and T
.
Examples:
spdiff((4,5,6))[1] == kron(I(6*5), spdiff1(4))
spdiff((4,5,6); order=1)[2] == kron(I(6), spdiff1(5), I(4))
spdiff((4,5,6); order=2)[3] == kron(spdiff2(6), I(4*5))
MRIFieldmaps.spdiff1
— Methodspdiff1(n::Int; ending::Symbol = :remove, T::Type = Int32)
Sparse n × n
matrix for 1st-order finite differences.
Option
T
element type, defaultInt32
to save memoryending
:remove
(default) remove first difference:zero
keep first row, akin to zero boundary conditions
MRIFieldmaps.spdiff2
— Methodspdiff2(n::Int; ending::Symbol = :remove, T::Type = Int32)
Sparse n × n
matrix for 2nd-order finite differences.
Option
T
element type, defaultInt32
to save memoryending
:remove
(default) remove first and last finite difference:zero
keep first and last rows, akin to zero boundary conditions:first
use 1st-order finite differences for first and last rows