qsm_core/unwrap/mod.rs
1//! Phase unwrapping methods
2//!
3//! Removes 2π wraps from MRI phase data.
4//!
5//! - [`unwrap_romeo`] / [`unwrap_romeo_multi_echo`] — ROMEO, region growing with
6//! quality-guided ordering ([`RomeoParams`])
7//! - [`unwrap_bestpath`] — best path (3D-SRNCP), globally sorted edge merging
8//! ([`BestPathParams`])
9//! - [`unwrap_prelude`] — PRELUDE, best-pair-first region merging ([`PreludeParams`]);
10//! the literature's reference unwrapper, kept as a baseline rather than a default
11//! - [`unwrap_medi_region_growing`] — MEDI's `unwrapPhase` (`mexUnwrap.c`, Tian Liu):
12//! magnitude-ordered region growing from the middle of the field of view, no mask, single
13//! precision, bit-identical to the MEDI toolbox
14//! - [`laplacian_unwrap`] — Laplacian unwrapping, with a [`LaplacianSolver`]: `Dct` (default;
15//! unweighted least squares, Neumann BC on the array) or `Fft { pad }` (Schofield & Zhu sin/cos
16//! method on the zero-padded volume, which reproduces STI Suite 3.0's `MRPhaseUnwrap`)
17//!
18//! All of the above read across slice boundaries. For a 2D multi-slice acquisition, where
19//! each slice carries its own receive phase offset, run one of them per slice with
20//! [`unwrap_slicewise`] / [`unwrap_slicewise_multi_echo`] ([`SliceWiseParams`]).
21
22pub mod romeo;
23pub mod bestpath;
24pub mod laplacian;
25pub mod prelude;
26pub mod medi_region_growing;
27pub mod slicewise;
28
29pub use romeo::{
30 unwrap_romeo, unwrap_romeo_multi_echo, correct_multi_echo_wraps,
31 calculate_weights_romeo, voxel_quality_romeo,
32 RomeoParams, RomeoWeightType,
33};
34pub use bestpath::{unwrap_bestpath, BestPathParams};
35pub use prelude::{unwrap_prelude, PreludeLabelling, PreludeParams};
36pub use medi_region_growing::{unwrap_medi_region_growing, MEDI_NOISE_RATIO};
37pub use slicewise::{
38 unwrap_slicewise, unwrap_slicewise_multi_echo, enforce_inter_echo_consistency,
39 SliceWiseParams,
40};
41pub use laplacian::{laplacian_unwrap, LaplacianSolver};
42
43/// Phase unwrapping method selection.
44///
45/// These select unwrappers only. Methods that unwrap *and* remove the background field
46/// (HARPERELLA, iHARPERELLA) live in [`crate::bgremove`].
47#[derive(Clone, Copy, Debug, PartialEq)]
48pub enum UnwrapMethod {
49 Romeo,
50 /// Laplacian unwrapping with [`LaplacianSolver::Dct`] (Neumann boundary on the array); see
51 /// [`laplacian_unwrap`]. Unwraps only — the background field is left alone. Call
52 /// [`laplacian_unwrap`] directly for [`LaplacianSolver::Fft`].
53 Laplacian,
54 /// Best path (3D-SRNCP); see [`unwrap_bestpath`]. The original Abdul-Rahman
55 /// algorithm, not ROMEO run with best-path weights — for that, set
56 /// [`RomeoParams::bestpath`].
57 BestPath,
58 /// PRELUDE (Jenkinson) with its settings; see [`unwrap_prelude`]. The unwrapper the
59 /// literature benchmarks against. It carries its [`PreludeParams`] so that every caller
60 /// that takes an `UnwrapMethod` (MCPC-3D-S's HIP unwrapping, the slice-wise unwrapper) runs
61 /// it with the caller's settings, not silently with the defaults.
62 Prelude(PreludeParams),
63 /// MEDI's region growing; see [`unwrap_medi_region_growing`]. The mask is not used (MEDI's
64 /// `unwrapPhase` takes none) and the magnitude is its quality map, so the callers that take
65 /// an `UnwrapMethod` pass theirs: MCPC-3D-S's HIP unwrapping its weight `sqrt(|HIP|)`, the
66 /// slice-wise unwrapper each slice's magnitude (required there).
67 MediRegionGrowing,
68}