Expand description
iQSM+ single-step deep-learning reconstruction (onnx feature).
iQSM+ (Gao 2024) extends iQSM with orientation-adaptive
latent feature editing (OA-LFE): the B0 direction (z_prjs) is a network input,
so oblique/sagittal/coronal acquisitions reconstruct correctly. The exported
graph takes six inputs: phase, mask, te (s), b0 (T), z_prjs (B0 dir,
[1,1,3]), and border (the LoT boundary mask, as for iQSM).
Pipeline (mirrors the authors’ inference.run_iqsm_plus): flip the phase sign,
erode the mask by a radius-3 sphere, crop to the brain bounding box + 16-voxel
margin, centre-pad to a multiple of 16, run, ×mask, then paste the result back
into the full grid. Multi-echo data is combined with (magnitude·TE)² weighting.
Only axial-ish acquisitions are handled directly here; the authors’ extra
axis-permutation for strongly oblique fields (|dir_y| > |dir_z|) is not applied.
Weights are not bundled; the caller passes the exported iqsm-plus.onnx bytes.
§Reference pipeline
As for iQSM (normalisation, bet2 -f 0.5 default mask), with two
differences in the authors’ sunhongfu/iQSM_Plus code:
- Resampling:
inference.py:443-471(andlegacy/matlab/iQSM_plus.m:175-210) interpolates anisotropic phase to an isotropic grid at the finest voxel size in the complex domain whenever the rounded grid would change. This crate does not resample. - Phase masking:
inference.py:425andlegacy/matlab/fcns/Save_Input_iQSMplus.mmultiply the phase by the unmodified mask before erosion. This crate does not; with an erosion radius of at least 1 that cannot change the result, since the 3×3×3 LoT stencil only reaches voxels inside the unmodified mask wherever its output survives the eroded mask.
§Agreement with the original
tests/models_onnx/field.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, iQSM+ a534d94 (iqsm-plus)
(QSMxT/QSM-CI#316; the fixture is regenerated in Actions by
tests/data/dl_field_qsmci_small.py): per echo, NRMSE 2.7e-4 to 3.3e-4 %, max |Δ| up to 6.8e-7
ppm: float32 rounding.
The original runs one echo at a time and combines the echoes afterwards with weights
(mag·TE)², in both of the authors’ implementations (see iqsm_plus_multi_echo), and so does
this crate. On the box’s first and third echoes the driver’s combination is (mag·TE)² of its
per-echo outputs to 1.6e-3 %, and mag·TE² weighting (iQSM’s MATLAB echo fit, which this crate
used for iQSM+ until 2026-10-31) differs from it by 3.1 % NRMSE (measured 2026-10-30);
iqsm_plus_multi_echo matches the (mag·TE)² combination of the original’s per-echo outputs
to 2.5e-4 % (measured 2026-10-31).
§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): iqsm.mask-bet.
Functions§
- iqsm_
plus - Run iQSM+ on a single echo of wrapped phase.
- iqsm_
plus_ multi_ echo - Multi-echo iQSM+: reconstruct each echo and combine them with weights (magnitude·TE)², i.e.
IqsmEchoWeighting::MagnitudeSquaredTeSquared; withoutmagnitudes, TE² alone. - iqsm_
plus_ 🔒with - One pass of the network. With
crop, on the eroded mask’s bounding box plus 16 voxels, centre-padded to a multiple of 16; without, on the whole input, which must already be one.