Skip to main content

Module lpcnn

Module lpcnn 

Source
Expand description

LPCNN dipole inversion (onnx feature).

LPCNN (Lai 2020) solves the dipole deconvolution by unrolling proximal gradient descent (iter_num = 3): each iteration takes a k-space data-consistency step with the dipole kernel D, then applies a learned 3D-CNN proximal operator gen. Only gen is a network (exported ONNX, a plain conv/BN/ReLU residual stack); the FFT data-consistency, the unroll, the learned step size alpha, and the mean/std normalization live here in Rust.

Input is the background-removed local field in ppm (single orientation). The authors’ Hz↔ppm round-trip (×tesla·γ then ÷tesla·γ) cancels, so the field is consumed directly in ppm. Weights are not bundled; the caller passes lpcnn.onnx.

§Reference pipeline

From Lai et al., MICCAI 2020 (arXiv:2008.05024), “Dataset Acquisition and Preprocessing”, and Sulam-Group/LPCNN:

  • Training data: 7T Philips, 1×1×1 mm, multi-echo GRE (TE1/ΔTE 5/5 or 2/2 ms), 4–5 orientations per subject, COSMOS labels; 64³ patches with a zero-padded full-size dipole.
  • Phase processing: best-path unwrapping, FSL BET, V-SHARP, then averaging of the echoes with TE between 10 and 30 ms.
  • Units: LPCNN/inference.py:50 divides the local phase (Hz) by tesla · γ (γ = 42.57747892 MHz/T), i.e. the network sees ppm; --tesla takes only 3 or 7.
  • Resampling: none in the authors’ code; the dipole kernel is built for the input’s voxel size.

§Agreement with the original

tests/models_onnx/dipole.rs runs it on a 36×32×28 box of in-vivo data (1 mm, 2.89 T, across the brain’s edge) against its original’s verified QSM-CI entry, LPCNN dd1ef2b (lpcnn) (QSMxT/QSM-CI#316; the fixture is regenerated in Actions by tests/data/dl_dipole_qsmci_small.py): NRMSE 3.7e-5 %, max |Δ| 8.5e-8 ppm (measured 2026-10-30): float32 rounding.

§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): lpcnn.mask-bet, lpcnn.bg-vsharp.

Constants§

ITER_NUM 🔒
LPCNN_ALPHA
Learned data-consistency step size (checkpoint alpha, Bmodel).
LPCNN_GT_MEAN
Ground-truth normalization (ppm), baked into the training pipeline.
LPCNN_GT_STD

Functions§

dipole_apply 🔒
D(v) = real(ifft3(fft3(v)·dk)) with dk in fftfreq (unshifted) layout.
lpcnn
Run LPCNN on a background-removed local field (ppm), column-major (nx,ny,nz). bdir is the B0 direction (for the dipole kernel). Returns χ (ppm), masked.
lpcnn_dipole_kernel 🔒
LPCNN dipole kernel D = 1/3 − (k·B̂)²/|k|² with k from fftfreq (DC at the array corner, D[0,0,0]=0) — the convention the model’s ortho-FFT expects.
lpcnn_tiled
Memory-bounded LPCNN via whole-algorithm overlap-tiling — the entire unrolled net is run on each patch sub-volume so peak memory is bounded (for the 32-bit WASM heap). LPCNN’s k-space data-consistency step is global, so tiling is strongly off-design and approximate; for real work run whole-volume (e.g. in QSMxT). See crate::inversion::tiled::tiled_volume_algorithm.
run_gen 🔒
Run the single-in/single-out proximal CNN on a column-major volume.