Diffusion-weighted imaging (DWI) model fitting and b-value extrapolation for 4D NIfTI and DICOM data.
DiffSuite is a modular Python toolkit for voxel-wise fitting of diffusion MRI signal models. It ships with a batch-friendly command-line interface, a FastAPI backend, and a full Electron + React + TypeScript desktop GUI with an embedded NIfTI viewer. Sixteen diffusion models are available β from simple ADC and DKI to IVIM, stretched-exponential DDC, DDVD vessel density, and experimental CTRW/FROC models β plus model-based synthetic signal extrapolation to arbitrary b-values.
Status: research / engineering tool. Not a medical device and not intended for clinical diagnosis.
Embedded NIfTI viewer β here showing a fitted diffusion map with the turbo colormap, slice navigation, and the selection/histogram study tools.
Model selection β every compatible model is listed with its equation, b-value requirements, outputs, and a one-line explanation; incompatible models stay visible as blocked (or can be force-fitted).
- Screenshots
- Highlights
- Architecture
- Supported models
- Installation
- Command-line usage
- Desktop GUI
- Building distributables
- REST API
- Output files
- Scientific background
- Repository layout
- Limitations and caveats
- License
- 16 registered models covering Gaussian diffusion, diffusion kurtosis, intravoxel incoherent motion (IVIM), stretched-exponential diffusion, vessel-density metrics, and experimental fractional models.
- Voxel-wise fitting over 4D volumes, slice by slice, with optional
ProcessPoolExecutorparallelism. - Automatic model proposal based on the b-values actually present in the acquisition β incompatible models are rejected with an explicit reason (and can be forced in the GUI).
- ROI-restricted fitting β draw an ellipse on the b0 reference and fit only those voxels.
- b-value extrapolation β use fitted parameter maps to synthesize the expected signal at any target b-value (e.g. b = 3000 s/mmΒ²).
- Automatic quality assessment β residual-based, family-aware quality verdict (
good/fair/poor), a 0β1 score, worst slices, and b-sampling hints. - Scalar ROI calculator β fit a curated subset of models to ROI-mean
(b, signal)pairs without loading a volume. - NIfTI and DICOM input β
.nii,.nii.gz, DICOM folders/files (viadcm2niix), with aSimpleITKfallback loader.
- 4-step wizard β Input β Model β Fit β Results.
- Embedded canvas NIfTI viewer with gray / turbo / jet colormaps, histogram-equalized windowing, and slice navigation.
- Interactive ROI drawing β drag to draw, move, and resize an ellipse; extrude across slices or keep a single slice.
- Multi-b extrapolation UI β select one or more target b-values and open each synthetic map in the viewer.
- Voxel selection + histogram study β lasso or brush a 3D voxel mask across slices, then run an in-browser histogram with Gaussian fit and scipy-matching statistics (mean, median, percentiles, std, skewness, excess kurtosis).
- Model reference table β every model shows its equation and a one-line explanation of the underlying principle.
- Themes β default, Gruvbox, and Cappuccin, persisted locally.
- Thin Python backend β the GUI calls exactly the same fitting code as the CLI through a local FastAPI server on
127.0.0.1:18923.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Electron renderer (React + TypeScript) β
β wizard Β· NIfTI viewer Β· ROI editor Β· histogram study β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β HTTP (127.0.0.1:18923)
βββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββ
β FastAPI backend (src/diffsuite/api.py) β
β sessions Β· model proposal Β· jobs Β· ROI Β· extrapolation β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β Python calls
βββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββ
β Fitting core (frontend.py Β· core.py Β· models/) β
β load NIfTI/DICOM Β· mask Β· group b-values Β· fit Β· save maps β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
CLI (`diffsuite`) ββββββββββββββββββββββββββββββββββββββββββββββ
same frontend.py / core.py / models/
The GUI does not reimplement any mathematics. It is a presentation layer over the same Python functions used by the CLI.
Models are registered in src/diffsuite/models/__init__.py (MODEL_REGISTRY). Each key maps to a fit_*_volume(...) function that returns a dictionary of 3D parameter maps.
| Key | Model | Equation | Required b-values | Method |
|---|---|---|---|---|
adc |
Apparent diffusion coefficient | S(b) = SβΒ·e^(βbΒ·ADC) |
β₯ 2 | Voxel, log-linear |
eadc |
Exponential ADC | eADC = e^(βADCΒ·b_max) |
β₯ 2 | Derived from ADC |
dki2d |
Diffusion kurtosis (2D) | S(b) = SβΒ·e^(βbD + bΒ²DΒ²K/6) |
β₯ 3 distinct b | Voxel, constrained TRF |
dki2d_fast |
Fast DKI | same as above | β₯ 3 distinct b | Voxel, closed-form log-linear |
dki2d_fast+ |
Fast DKI plus | same as above | β₯ 3 distinct b | Adds intravoxel skew + fused maps |
dki_ais_u |
DKI AIS β unconstrained | same as above | β₯ 3 distinct b | Volume-level iterative (Yan 2014) |
dki_ais_c |
DKI AIS β constrained | same as above | β₯ 3 distinct b | Adds D β₯ 0, K β₯ 0, K β€ 3/(b_maxΒ·D) |
dki_ais_sc |
DKI AIS β smoothed/constrained | same as above | β₯ 3 distinct b | CAIS + 3Γ3Γ3 ADC smoothing |
akc_adci |
Secant-based DKI approximation | ADC(b_mid) β D β (DΒ²K/3)Β·b_mid |
β₯ 3 distinct b | Voxel, secant regression |
ddc |
Stretched exponential (DDC) | S(b) = SβΒ·e^(β(bΒ·DDC)^Ξ±) |
β₯ 3 + b0 | Voxel, bounded Ξ± β (0, 1] |
ivim_seg |
IVIM β segmented | S(b) = Sβ[(1βf)e^(βbD) + fΒ·e^(βbD*)] |
β₯ 4; β₯ 3 b > 200; β₯ 2 b < 200 | Two-stage voxel fit |
ivim_full |
IVIM β full nonlinear | same as above | β₯ 4; β₯ 2 b > 200; β₯ 2 b < 200 | Simultaneous voxel fit |
dki_ivim |
Combined DKI + IVIM | S(b) = Sβ[fΒ·e^(βbD*) + (1βf)e^(βbD + bΒ²DΒ²K/6)] |
β₯ 5; β₯ 2 b > 200; β₯ 2 b < 200 | Simultaneous voxel fit |
ddvd |
Diffusion-derived vessel density | DDVD = S(b0) β S(b_low) |
b0 + β₯ 1 b in [10, 50] | Volume-level, 3Γ3Γ3 smoothing |
ctrw |
Continuous-time random walk (experimental) | S(b)/Sβ = E_Ξ±[β(bΒ·D)^Ξ²] |
β₯ 5; b_max β₯ 2000 | Voxel, Mittag-Leffler |
froc |
Fractional-order calculus (experimental) | S(b)/Sβ = e^(βDΒ·ΞΌ^(2Ξ²β2)Β·b^Ξ²) |
β₯ 5; b_max β₯ 2000 | Voxel |
extrap |
Model-based extrapolation | Ε(b_target) from fitted parameters |
β | Not a fittable volume model |
Per-model documentation with parameter ranges, assumptions, and references lives in src/diffsuite/models/help/.
- Python β₯ 3.9
dcm2niixinPATH(DICOM input only)- Node.js β₯ 18 and npm (desktop GUI only)
- Windows, Linux, or macOS
Portable GUI builds are published on the Releases page:
- Windows x64 β
DiffSuite-0.2.1-portable.exe(single self-extracting executable) - Linux x64 β
DiffSuite-0.2.1.AppImage(chmod +xand run; use--appimage-extract-and-runif FUSE is unavailable)
Both are thin Electron shells and still require Python + the DiffSuite package on the target machine β see Portable GUI prerequisites.
git clone https://github.com/lippisch2/DIFFSUITE.git
cd DIFFSUITE
# Core fitting package and `diffsuite` command
pip install -e .
# Optional FastAPI backend used by the desktop GUI
pip install -r requirements-api.txtCore dependencies: numpy, nibabel, scipy, pydicom, rich, tqdm, matplotlib, SimpleITK.
pip install -r requirements-api.txt
cd electron-app
npm install
npm run devnpm run dev builds the renderer/main bundles and launches Electron. The Electron main process automatically spawns python -m uvicorn diffsuite.api:app on port 18923, waits for /api/status, then opens the window.
# Fit a 4D NIfTI volume (interactive model selection)
diffsuite path/to/dwi.nii.gz
# Provide b-values manually if no .bval sidecar exists
diffsuite path/to/dwi.nii.gz --bvals "0 50 800 1400"
# DICOM folder or file (requires dcm2niix)
diffsuite path/to/dicom_folder --bvals "50 800 1400"
# Open the ROI viewer after fitting
diffsuite dwi.nii.gz --open-roi --roi-map dki2d_fastThe interactive flow asks which model to fit and how many worker processes to use, then writes parameter maps next to the input volume.
Input handling:
.nii/.nii.gzare loaded withnibabel;SimpleITKis used as a fallback.- DICOM folders/files are converted with
dcm2niix. - If a
.bvalsidecar is absent, pass--bvals. - b-values are rounded to integers and grouped before fitting.
- Input β choose a NIfTI/DICOM file or drag it in. The backend loads the volume, detects b-values, and prepares a b0 reference.
- Model β models are ranked into applicable/rejected groups from the detected b-values. Each row shows its equation and principle. A "force blocked models" toggle allows deliberately fitting an under-sampled model.
- Fit β choose worker count, optionally limit fitting to an ellipse ROI drawn on the b0 reference, and watch real progress as slices complete.
- Results β inspect every output map, read per-parameter legends, open maps in the embedded viewer, run a histogram study on selected voxels, or extrapolate to one or more target b-values.
- Canvas-based NIfTI rendering with three colormaps.
- Ellipse ROI: drag to draw, drag the body to move, drag the handle to resize; apply to one slice or extrude through the volume.
- Optional ROI-based colormap windowing.
- 3D voxel selection with lasso (double-click to close) or circular brush; selection accumulates across slices.
- Histogram study computes N, mean, median, P10/P50/P75/P90, min/max, standard deviation, skewness, and excess kurtosis, plus a Gaussian fit. Formulas deliberately match SciPy (
bias=False).
The discreet header dot cycles default β Gruvbox β Cappuccin; the choice is stored in localStorage as diffsuite-theme.
All build commands run from electron-app/.
npm install
# Windows: NSIS installer + portable executable
npm run build:win
# Linux: AppImage
npm run build:linux
# macOS: DMG
npm run build:macelectron-builder writes artifacts to dist-electron/dist/. The Windows build config includes both nsis and portable targets; the portable target produces a single self-extracting .exe that runs without installation.
The portable executable is a thin Electron shell: it starts the Python backend as a subprocess. The target machine therefore needs:
- Python 3.9+ available as
python(Windows) orpython3(Linux/macOS). - The DiffSuite package installed:
pip install -e .(orpip install diffsuiteonce published). - Backend dependencies:
pip install -r requirements-api.txt.
If the backend cannot start, the app reports the failure and exits after a 30-second timeout.
Note on prebuilt binaries: release artifacts are convenience builds of the source in this repository. Because the backend is Python, the portable GUI is not fully self-contained yet; bundling a frozen Python runtime is tracked as future work.
The FastAPI backend (src/diffsuite/api.py) listens on http://127.0.0.1:18923 and enables CORS for the Electron renderer.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/status, /api/health |
Health and version |
POST |
/api/load |
Load a volume by path ({path, bvals?}) β session metadata |
POST |
/api/load/upload |
Multipart upload variant |
POST |
/api/models |
Applicable/rejected models for a list of b-values |
POST |
/api/fit |
Start a fit job ({session_id, model, workers}) β job_id |
GET |
/api/fit/{job_id} |
Job status, progress, slices, outputs, error |
GET |
/api/results/{job_id} |
Output map list |
GET |
/api/reference/{session_id} |
b0 reference NIfTI |
POST |
/api/roi |
Rasterize an ellipse into a 3D ROI mask |
POST |
/api/roi/clear |
Clear the session ROI |
GET |
/api/roi/mask/{session_id} |
Serve the stored ROI mask |
GET |
/api/nifti?path=<abs> |
Serve a NIfTI file |
POST |
/api/extrapolate |
Synthetic map at a target b-value |
GET |
/api/roi-calc/models |
Models available for the scalar ROI calculator |
POST |
/api/roi-calc |
Fit a curated model to scalar ROI-mean signals |
Run it directly:
python -m uvicorn diffsuite.api:app --host 127.0.0.1 --port 18923Interactive API docs are available at http://127.0.0.1:18923/docs.
Fits are written next to the input volume using the pattern:
{stem}_{model}_{parameter}.nii.gz
Examples:
dwi_dki2d_s0.nii.gz
dwi_dki2d_d.nii.gz
dwi_dki2d_k.nii.gz
dwi_dki2d_residual.nii.gz
dwi_dki2d_fast_plus_skew.nii.gz
Model keys containing awkward filename characters are canonicalized (dki2d_fast+ β dki2d_fast_plus) so the CLI and API always produce identical names.
| Model family | Reference |
|---|---|
| ADC / monoexponential | Basser PJ, Mattiello J, Le Bihan D. Magn Reson Med. 2005. |
| Diffusion kurtosis imaging | Jensen JH, Helpern JA, et al. Magn Reson Med. 2005;53:1432β1440. |
| IVIM | Le Bihan D, Breton E, Lallemand D, et al. Radiology. 1988;168:497β505. |
| Stretched-exponential DDC | Kastrup A, Li T, Ying B, et al. Magn Reson Med. 2003;50:727β734. |
| DKI alternative iteration scheme (AIS/UAIS/CAIS/SCAIS) | Yan et al. 2014. |
| DDVD | Ni CX et al. BMC Med Imaging. 2025;25:79. |
| CTRW | Metzler R, Klafter J. Phys Rep. 2000. |
| FROC | Fractional-order calculus diffusion literature (experimental). |
A detailed source-level review β including signal-equation verification, parameter bounds, implementation consistency findings, and recommendations β is available in SCIENTIFIC_VERIFICATION_REPORT.md. A worked comparison of AKC-ADC(i) against fast DKI is in akc_adci_vs_dki2d_fast_report.pdf.
src/diffsuite/models/quality.py evaluates each fit from the residual maps using an S0-normalized relative error, family-aware thresholds, and an overall verdict. The GUI attaches this report to every job, so a numerically converged fit is not silently presented as a good fit.
DIFFSUITE/
βββ src/diffsuite/
β βββ cli.py # `diffsuite` entry point
β βββ frontend.py # loading, b-value grouping, interactive CLI
β βββ core.py # fit dispatch helper
β βββ api.py # FastAPI backend for the GUI
β βββ models/
β β βββ __init__.py # MODEL_REGISTRY
β β βββ common.py # slice-wise voxel fitting engine
β β βββ adc.py, eadc.py, dki2d.py, dki2d_fast.py, ...
β β βββ extrapolation.py # synthetic signal at target b
β β βββ quality.py # residual-based fit quality assessment
β β βββ roi_calc.py # scalar ROI calculator
β β βββ mittag_leffler.py
β β βββ help/ # per-model equations and references
βββ electron-app/
β βββ electron/ # main process + preload bridge
β βββ src/ # React renderer (wizard, viewer, components)
β βββ electron-builder.yml
β βββ electron.vite.config.ts
βββ niviewer.py # standalone matplotlib ROI viewer
βββ old/ # legacy scripts (not used)
βββ requirements-api.txt
βββ pyproject.toml
βββ SCIENTIFIC_VERIFICATION_REPORT.md
- Research software. Parameter maps are model estimates, not calibrated clinical measurements.
- Grid search / local minima. Nonlinear models (
dki2d,ivim_full,dki_ivim,ctrw,froc) depend on initial guesses and can settle in local minima at low SNR. - Sparse protocols degrade fits. The GUI surfaces applicability requirements, but forcing a model with too few b-values will produce unreliable maps by design.
- IVIM S0 bias. IVIM family models take
S0from the minimum-b volume; whenb_min > 0, this slightly underestimates trueS0. Prefer protocols with an actual b = 0. - DICOM conversion depends on
dcm2niixand its gradient/b-value sidecars. - No test suite or CI is configured yet. Validation is currently the scientific review report plus manual comparisons.
- Portable GUI needs Python. See Portable GUI prerequisites.
MIT License. See LICENSE.
DiffSuite builds on the scientific work cited above and on the open-source Python scientific stack (NumPy, SciPy, nibabel, SimpleITK), FastAPI, Electron, React, Vite, and nifti-reader-js.

