Expand description
FANSI nonlinear TV / TGV dipole inversion.
Nonlinear total-variation (nlTV) and nonlinear total-generalized-variation (nlTGV) QSM dipole inversion with a nonlinear (wrapped-phase) data-fidelity term, solved with ADMM plus an inner complex-argument Newton iteration.
The nonlinear fidelity models the field data as exp(i * D x) and matches
it to the wrapped local-field phase, which makes the reconstruction robust to
phase-wrap / high-field regimes.
References:
- nlTV: Milovic, C., Bilgic, B., Zhao, B., et al. (2018). “Fast nonlinear susceptibility inversion with variational regularization.” Magnetic Resonance in Medicine, 80(2):814-821. https://doi.org/10.1002/mrm.27073
- nlTGV: the total-generalized-variation variant of the above.
Ported faithfully from the FANSI toolbox nlTV.m and nlTGV.m
(https://gitlab.com/cmilovic/FANSI-toolbox).
§Units and weights
Like the other inversions, these take the local field in ppm and return ppm. nlTV.m and nlTGV.m
work on the phase in radians, so the field is converted with 2*pi*gamma*b0*te first and the
result converted back at the end; left in ppm, sin(x) ~ x and the data term is not nonlinear.
b0 and echo_times are scan parameters that the pipeline fills from metadata, and
FansiParams::te picks the echo time the conversion uses (by default the reference’s choice;
see there).
The data weight is the magnitude, normalised as in FANSI’s in vivo example
(min(2*mask*mag/max(mag), 1)), and squared as nlTV.m/nlTGV.m square
params.weight. The magnitude is required: with a flat (mask) weight, the Newton
step’s denominator W*cos(z2 - phase) + mu2 reaches 0 where the phase nears +-pi
and the solver diverges (as nlTV.m does).
The finite differences are FANSI’s, on unit spacing whatever the voxel size.
§Reference pipeline
FANSI-toolbox at commit 93044a3 (https://gitlab.com/cmilovic/FANSI-toolbox). Its only
full pipeline is script_DICOM_Philips.m (3T Philips, 5 echoes, TE1 4.0 ms, spacing 3.7 ms,
0.73x0.73x1 mm, B0 along z; header L1-6), which says it is “NOT an optimized pipeline”:
- Mask: magnitude (M0) threshold plus an R2* range, then morphology, ending with a 2-voxel erosion “to avoid data corruption in the cortical areas” (L125-170); L126 “We encourage to use dedicated tools as BET2”.
- Unwrapping: SEGUE per echo (L190-194); L183-187 also recommend ROMEO, and L196-197 say “Avoid Laplacian-based unwrapping for multiecho processing, as they remove harmonic components of the phase”.
- Echo combination: a nonlinear multi-echo fit (
nlme_L2gradient, weightmag*TE, L259-276), which also gives the noise mapcnoise. - Background removal: FANSI’s own multiscale SMV,
msmv_noextrapolation(..., 5)(L335); L290 allows LBV, PDF or V-SHARP instead. (This MSMV is not the mSMV ofbg_removal.msmv_refine.) - Input:
local*deltaTE,deltaTE = TE(4) - TE(2)with the comment “You may use also any individual echo time” (L364, L370). Weightm0.*mask./cnoise, divided by its maximum (L371-372). nlTGV is run with the same parameters as wTV (L421). - alpha1: no default in
nlTV.m/nlTGV.m(required field); the toolbox’s demos use 2e-4 (script_fansi_phantom.mL196,script_qsmchallenge.mL73) and 3e-4 with mu1 = 1e-2 for nlTV on the 2016 challenge data (script_qsmchallenge.mL111-112), which is the challenge’s own LBV local field and BET mask eroded by 5 voxels (L22-24). The default here is that 2e-4; the in vivo pipeline picks alpha1 by L-curve / frequency analysis (L374-410). - Default weight in
nlTV.m/nlTGV.mis ones (defaultW = ones(N), with a warning). Every demo call ofnlTV/nlTGVpasses a magnitude-derived weight (script_fansi_phantom.mL199 “Recommended for nonlinear algorithms”,script_cosmos_phantom.mL88,script_qsmchallenge.mL106-108); the mask-only weights in the demos go to the linearwTV/wTGV.
§Parity
Against the verified original (QSM-CI pair fansi-nltv, fansi-nltgv; FANSI-toolbox 93044a3, identical to
licensed MATLAB R2023b), final-map χ NRMSE at both sides’ defaults on QSM-CI’s simulated head
and the KKI travelling head (QSM-CI parity run 41403629314, QSM.rs#399–#403): nlTV sim 0.0069 %, KKI 0.0030 %; nlTGV sim 0.0063 %, KKI 0.0039 %, from
nlTV 11.0 % / 9.5 %, nlTGV 11.0 % / 9.6 % (sim / KKI) before. The kernel was the whole gap. What remains is
single (MATLAB) vs double (here) precision and FANSI’s γ, 42.58 against the crate’s 42.576
(the wrappers keep theirs). Fixture: tests/fansi_qsmci_parity.rs (relative L2 below 1e-5
on an oblique, anisotropic phantom).
§Pipeline rules
The facts above that a configuration can depart from are published as rules in
crate::pipeline::rules::RULES (each with its strength, basis, reason and source): fansi.no-laplacian-multi-echo, fansi.te-spacing.
Structs§
- Fansi
Params - FANSI nlTV/nlTGV parameters (nlTV.m / nlTGV.m defaults where they have them).
Functions§
- fansi
- FANSI nlTV/nlTGV dipole inversion.
- nltgv 🔒
- Nonlinear total-generalized-variation dipole inversion (FANSI
nlTGV.m). - nltv 🔒
- Nonlinear total-variation dipole inversion (FANSI
nlTV.m). - norm2 🔒
- L2 norm of a real slice.
- phase_
and_ 🔒weight - ppm -> radians, and the squared data weight (see module docs).
- spectral_
mul_ 🔒assign - Multiply a complex spectral array in place by a complex multiplier array.