Expand description
AMP-PE: Approximate Message Passing with built-in Parameter Estimation for QSM.
Nonlinear dipole inversion solved with Generalized Approximate Message Passing (GAMP) over a linearized wrapped-phase (complex-exponential) forward model, using a Laplace sparse-wavelet prior and a Gaussian-mixture noise model that absorbs phase outliers.
Ported from the reference MATLAB implementation
(https://github.com/EmoryCN2L/QSM_AMP_PE, Huang et al., Magn. Reson. Med.
2023) as packaged for the QSM-CI dipole stage (recon.m +
amp_pe_mri_qsm_awgn.m / amp_pe_mri_qsm_awgn_mix.m). This is the
dipole-inversion stage only: the local (tissue) field is provided, turned into
a simulated single-echo phase, and fed to the two-step AMP-PE solve
(single-Gaussian warm-up → Gaussian-mixture final).
§Design notes / fidelity
- The forward dipole operator, wavelet transform (periodic db1/db2), and
erfcxall match the MATLAB reference (seeutils::wavelet,utils::special). - The reference estimates operator Frobenius norms with 2 random probes. Here
they are computed exactly (the wavelet transform is orthonormal, so its
norm is
sqrt(coef_len); the weighted-dipole norm has a closed form). This is deterministic and a strict improvement; the verification harness injects the same exact values into MATLAB so the two agree to numerical precision. - Input local field is ppm-scale (crate convention);
mut_cstconverts ppm to radians at the simulated echo time. - The L2 (chiL2) seed is computed on the field masked to the ROI (as recon.m does) — background outside the mask must not enter the seed.
- Verified against the MATLAB reference to ~2e-10 on the real 164x205x205
phantom when both use a double-precision seed. The reference’s
dipole_kernel_angulatedcasts the seed kernel tosingle; in phase-wrapping regions (|phase|>pi) the nonlinear solve is multistable, so that ~1e-7 seed perturbation can select a different local solution there. This crate uses full double precision (a strict improvement).
Structs§
- AmpPe
Params - Parameters for the AMP-PE inversion.
- Dipole
Op 🔒 - Dipole forward/adjoint operator over a padded grid, with mask gather/scatter.
- GampCfg 🔒
- Static GAMP configuration.
- Gamp
Snapshot 🔒 - A restore point for backing out of a divergent GAMP sweep.
- Gamp
State 🔒 - Persistent GAMP state carried across linearization iterations.
- MixState 🔒
- Gaussian-mixture noise parameters (single component + outlier component).
Constants§
- DAMP_
DIVERGE_ 🔒FACTOR - Cost blow-up factor (relative to the best fit so far) treated as divergence.
- DAMP_
GROW 🔒 - Factor by which damping relaxes back towards the configured value after an accepted sweep.
- DAMP_
MIN 🔒 - Damping floor; below this the iteration is making no progress and we stop with the last good state.
- DAMP_
SHRINK 🔒 - Factor applied to the damping when a sweep is rejected.
- EPS 🔒
- MAX_
BACKTRACKS 🔒 - Cap on rejected sweeps per GAMP call, so a pathological case cannot spin.
- PARAM_
CHUNK 🔒 - Chunk length for the deterministic parallel reductions in the GAMP parameter estimation. Fixed size ⇒ the result is independent of the thread count.
Functions§
- a_
qsm_ 🔒mult - A_qsm forward: image -> masked complex measurement.
- a_
qsm_ 🔒multtr_ real - real(A_qsm^H * s): masked complex -> full-volume real.
- amp_pe
- AMP-PE nonlinear dipole inversion.
- build_
wave_ 🔒mask - Build the morphology mask: coefficients whose magnitude exceeds a cumulative-energy threshold of the magnitude image’s wavelet coefficients.
- chi_
l2_ 🔒seed - Direct L2 (Tikhonov, gradient) QSM solver used only to seed distributions.
Matches
chiL2.m:real(ifftn(conj(K) fftn(phase) / (|K|^2 + beta*E2 + eps))) * mask. - crop_
volume 🔒 - data_
fit 🔒 - Plain data fit
||A x - y||^2 / m, the quantity the divergence guard watches. - frob_
qsm_ 🔒sq - Frobenius norm squared of the weighted-dipole operator
A_qsm. - gamp_
awgn 🔒 - One GAMP call with single-Gaussian (AWGN) noise. Returns updated
tau_w_1. - gamp_
awgn_ 🔒mix - One GAMP call with Gaussian-mixture noise (final stage).
- input_
function 🔒 - Laplace input function: soft-threshold with the morphology mask passing large
coefficients through unshrunk. Returns
(x_hat_psi, tau_x). - input_
parameter_ 🔒est - EM update of the Laplace scale parameter
lambda(single cluster). - linearize 🔒
- Build the linearized measurement for the current estimate.
- mix_
output_ 🔒function - Gaussian-mixture output function (single Gaussian + zero-mean outlier Gaussian).
Returns
(x_hat, tau_x)wherex_hatis the posterior-mean noise estimate. - mix_
output_ 🔒parameter_ est - EM update of the mixture parameters
omega,phi,psi(theta, gamma fixed). - note_
guard_ 🔒firing - Record that the divergence guard rejected a sweep. Compiled away outside tests.
- pad_
volume 🔒 - var 🔒
- Sample variance (MATLAB
var, normalized byn-1). - var_
complex 🔒 - Sample variance of a complex vector (MATLAB
varon complex data:mean(|x - mean|^2) * n/(n-1)). - wavelet_
block 🔒 - Shared wavelet-domain GAMP block (identical between AWGN and mixture stages).