Methods list
MRIFieldmaps.MRIFieldmapsMRIFieldmaps.EchotimeMRIFieldmaps.RealUMRIFieldmaps.b0initMRIFieldmaps.b0mapMRIFieldmaps.b0mapMRIFieldmaps.b0modelMRIFieldmaps.b0scaleMRIFieldmaps.coil_combineMRIFieldmaps.phasecontrastMRIFieldmaps.spdiffMRIFieldmaps.spdiff1MRIFieldmaps.spdiff2
Methods usage
MRIFieldmaps.MRIFieldmaps — ModuleMRIFieldmapsModule 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 — TypeRealUA 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)nesets of complex images fornc ≥ 1coilsechotime (ne)vector ofne ≥ 2echo times (only first 2 are used)
Options
smap (dims..., nc)complex coil maps; defaultnothingthresholdsetfinitvalues 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 3Trelamprelative amplitudes in multi-species water-fat (def:[])fbandfrequency bandwidth forfdict; defaultfloor(1 / minimum(echo time spacing))`nfnumber 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
finitinitial 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 nth 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)nesets of complex images fornc ≥ 1coilsechotime::Echotime (ne ≥ 2)echo time offsets (in seconds)
Options
finit (dims)initial fieldmap estimate (in Hz); default fromb0init()smap (dims..., nc)complex coil maps; defaultnothingmask (dims...)logical reconstruction mask; default:trues(size(finit))ninner# of inner iterations for monotonic line search default:3inner iterationsb0init_args::NamedTuple = (;)options forb0init, such asthresholdniter# of outer iterations (def:30)orderorder of the finite-difference matrix (def:2)l2blog2of regularization parameter (def:-6)gamma_typeCG direction::PR= Polak-Ribiere (default):FR= Fletcher-Reeves
preconPreconditioner::I(nothing):diag:cholmay 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 3Trelamprelative amplitudes in multi-peak water-fat (def:[1])lldl_args::NamedTupleoptions forlldl, default:(;memory=2)track::Booliftruethen track cost and save all iterations (def:false)chat::Bool = true#@infoupdates each iterationchat_iter::Int = 10# print progress report every few iterations.
Out
fhatfinal fieldmap estimate in Hztimes (niter+1)wall time for each iterationout::NamedTuplethat contains:(xw, xf) (dims)water / fat images if!iszero(df)finit (dims)initial fieldmap
- if
track == truethenoutalso 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 (npis # of pixels in mask)zdata (np, ne)nesets of coil-combined measurementssos (np)sum-of-squares of coil mapsechotime (ne)vector ofneecho 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 orTupleofneecho 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 3Trelamprelative 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)nesets of complex images fornccoils
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)^2di = 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 fornedifferent echo timesechotime (ne)echo times (units of sec if fieldmap is in Hz)
Option
dmax::Realthreshold for relativedivalue (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 ≥ 1sets of complex images fornc ≥ 1coilssmap (dims..., nc)complex coil maps (optional)
Out
zdata (dims..., ne)complex coil combination:sum_c smap[c]' * ydata[c] ./ sosorsum_c ydata[c,1]' * ydata[c] ./ sos(ifsmapnot provided orisnothing(smap))sos (dims...)sum-of-squares:sum_c |smap[c]|^2orsqrt.(sum_c |ydata[c,1]|^2(ifsmapnot 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)nesets of complex images fornc ≥ 1coilsechotime::Echotime (ne = 2)echo time offsets
Out
pc (dims...)phase contrast (or field map, ifechotimeis 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
Telement type, defaultInt32to save memoryending:remove(default) remove first difference:zerokeep 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
Telement type, defaultInt32to save memoryending:remove(default) remove first and last finite difference:zerokeep first and last rows, akin to zero boundary conditions:firstuse 1st-order finite differences for first and last rows