Skip to main content

Module susep_net

Module susep_net 

Source
Expand description

SUSEP-Net deep-learning χ-separation (onnx feature).

SUSEP-Net (Li/Gao/Sun 2025) is a dual-branch 3D U-Net that maps three guidance maps — QSM (χ_total, ppm), R2′ (Hz), local field (ppm) — to paramagnetic (χ+) and diamagnetic (χ−) source magnitudes. Clean NCDHW ONNX export (three inputs qsm,r2prime,lfs; two outputs chi_pos,chi_neg).

Recipe (mirrors the authors’ recon.py): z-score each input by the training stats, zero outside the mask, post-pad each dim to a multiple of 8, run, de-normalize the outputs, crop, and mask. We return χ− as a signed (≤ 0) value to match the crate’s separation convention (chi_pos ≥ 0, chi_neg ≤ 0, chi_total).

Deviation: both decoders end in a 1×1 convolution with no activation (SQNet.py), so a de-normalised magnitude can be negative, and test_demo.py saves it as it is. Here negative χ+ and |χ−| are set to 0, since a negative source magnitude has no physical meaning, and χ_total is χ+ + χ− after that. Every non-negative value is the network’s unchanged.

Array orientation. SUSEP-Net is a different group’s network from the χ-sepnet family and its training orientation has not been established here; the authors’ recon.py does not reorient, and neither does this function (it is handed a Grid, not an affine). Treat it as assuming the usual axial convention — slice axis along B0 — and see chisepnet for how little that turned out to be worth on the χ-sepnet side; no equivalent measurement has been made for this network.

Whole volume vs patches. The authors run the whole volume in one forward pass, and SusepNetParams::patch defaults to that (None). Activations then scale with the volume, which a 32-bit host cannot afford — at 1 mm whole-brain the first conv block alone runs to several GB against a 4 GB WASM heap — so such a host passes a patch and gets an overlapping sliding window (0.75 stride, overlaps averaged) with memory bounded by the patch. Tiling a net trained on whole volumes is an approximation: each patch is blind to structure outside it. Patch dimensions must be multiples of 8 (three pooling levels).

Weights are not bundled; the caller passes the exported susep-net.onnx bytes (see crate::models).

§Reference pipeline

Li M., …, Sun H., Gao Y. 2025 (arXiv:2506.13293):

  • Training (§2.3): 3 T (Philips Ingenia Elition X), 0.9 × 0.9 × 1 mm, 8 echoes, TE1/ΔTE = 4.1/4.0 ms, with 64³ patches. The training inputs are simulated by the forward model (Eq. 1) from APART-QSM-reconstructed χ+/χ− and decay-kernel maps, so the network was never fit to one particular field-mapping chain.
  • In-vivo inputs (§3.2): the local field from iQFM and the QSM from iQSM+, both computed directly from the multi-echo GRE phase. R2* and R2 come from mono-exponential fits in STI Suite (multi-echo GRE and multi-echo SE), and R2’ = R2* − R2.
  • R2’ enters in Hz with no D_r scaling (the input normalisation in SusepNetNorm).

Reference: Li, M., Chen, C., Li, Z., …, Sun, H., Gao, Y. (2025). “SUSEP-Net: Simulation-Supervised and Contrastive Learning-based Deep Neural Networks for Susceptibility Source Separation.” arXiv:2506.13293. Code: https://github.com/YangGaoUQ/SUSEP-Net

§Agreement with the original

tests/models_onnx/separation.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, SUSEP-Net (susep-net) (QSMxT/QSM-CI#316; the fixture is regenerated in Actions by tests/data/dl_separation_qsmci_small.py): χ+ and χ− NRMSE 2.4e-5 %, max |Δ| 1.7e-7 ppm (measured 2026-10-30): float32 rounding. The original moves by about 1e-7 relative from run to run, since its wrapper uses every CPU.

§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): susep-net.qsm-iqsm-plus.

Structs§

SusepNetNorm
Training z-score constants for SUSEP-Net (all_mean_std.mat): each field is (mean, std). Inputs are normalized (x-mean)/std; outputs de-normalized y*std + mean.
SusepNetParams
Inference parameters for susep_net.

Constants§

POOL_MULTIPLE
Three 2× pooling levels, so every patch dimension must be a multiple of this. Public (and built without onnx) so a host can check a patch, or state the rule, without restating the number.
WASM_PATCH
A patch that fits a 32-bit (WASM) heap alongside a browser pipeline’s other volumes. Peak memory, measured natively (single-threaded): about 1.8 KB per patch voxel plus ~0.9 GB for the parsed model and buffers, so 2.0 GB at this patch, 2.8 GB at 128×128×64 and 12.5 GB for a whole 184×256×128 volume. On the QSM-CI χ-separation phantom it agrees with the whole volume to r ≥ 0.998 on both maps (tests/chisep_xsepnet.rs).

Functions§

susep_net
Run SUSEP-Net χ-separation.