Skip to content

Model catalog

The framework has one model of its own — the unified white-matter model below — and reproduces the published literature as thin factories around the same shared primitives. Every entry is an ordinary MultiCompartmentModel: forward-simulate with model(scheme, **params), fit with one model.fit(scheme, data) call.

The unified white-matter model

The framework's own model — the analytical inverse of the dmipy-sim Monte-Carlo forward truth.

It is not a bespoke class: the canonical white-matter substrate is an ordinary MultiCompartmentModel built from the same primitives as everything below — C1Stick (intra-axonal), G2Zeppelin (extra-axonal) and S1Dot (stuck myelin), each wrapped in an OccupancyGatedModel that carries the opt-in occupancy-gated factors: transverse relaxation (T2) and intra-pore + exterior surface relaxivity. A single Gamma outer-diameter distribution drives both surface factors, and the whole thing forward-simulates and fits through the standard machinery, exactly like NODDI. Diffusion-only — no susceptibility, gradient-/stimulated-echo, or T1 physics.

Each compartment is a diffusion primitive wrapped in an OccupancyGatedModel carrying the occupancy-gated factors (surface relaxivity + T2) — one Gamma outer-diameter distribution drives both surface factors:

from dmipy_fit.signal_models.cylinder_models import C1Stick
from dmipy_fit.signal_models.gaussian_models import G2Zeppelin
from dmipy_fit.signal_models.sphere_models import S1Dot
from dmipy_fit.signal_models.attenuation import (
    OccupancyGatedModel, TransverseRelaxation,
    IntraPoreSurfaceRelaxivity, ExteriorSurfaceRelaxivity)
from dmipy_fit.white_matter.surface import exterior_surface_to_volume

if S_ext_over_V is None:
    S_ext_over_V = exterior_surface_to_volume(
        f_axon, gamma_shape, gamma_scale_outer_diameter)
intra = OccupancyGatedModel(C1Stick(), [
    IntraPoreSurfaceRelaxivity(
        gamma_shape=gamma_shape,
        gamma_scale_outer_diameter=gamma_scale_outer_diameter,
        volume_weighted=True),
    TransverseRelaxation(),
])
extra = OccupancyGatedModel(G2Zeppelin(), [
    ExteriorSurfaceRelaxivity(S_ext_over_V=S_ext_over_V),
    TransverseRelaxation(),
])
# myelin water is ~stuck (radial D ~ 0): a stationary Dot, short-T2 only
myelin = OccupancyGatedModel(S1Dot(), [TransverseRelaxation()])
compartments = [intra, extra, myelin]
if include_csf:
    compartments.append(OccupancyGatedModel(G1Ball(), [TransverseRelaxation()]))
return compartments

then assembled into a standard MultiCompartmentModel with one shared fibre orientation — no bespoke class:

from dmipy_fit.core.modeling_framework import MultiCompartmentModel

geom = {k: overrides[k] for k in
        ('gamma_shape', 'gamma_scale_outer_diameter', 'f_axon', 'S_ext_over_V')
        if k in overrides}
compartments = white_matter_compartments(include_csf=include_csf, **geom)
model = MultiCompartmentModel(models=compartments, S0_global=True)
# one coherent fibre: the extra-axonal orientation follows the intra-axonal
model.set_equal_parameter('OccupancyGatedModel_1_mu',
                          'OccupancyGatedModel_2_mu')
parameters = canonical_parameters(include_csf=include_csf, **overrides)
parameters.pop('OccupancyGatedModel_2_mu', None)   # linked to _1_mu
return model, parameters

That composition is packaged with canonical healthy-WM-at-3 T defaults as one call — model, params = build_white_matter_model() — then model(scheme, **params) forward-simulates and model.fit(scheme, data, solver="jax") fits, exactly like the literature models below.


Literature models

Each factory below lives in dmipy_fit.custom_optimizers.reference_models and returns a configured MultiCompartmentModel (or spherical-mean model) in a few lines.

from dmipy_fit.custom_optimizers import reference_models as models
mcm = models.noddi()          # any factory below
fit = mcm.fit(scheme, data, solver="jax")

Gaussian / tensor

ball() A1

Isotropic Gaussian (single ADC).

Stejskal & Tanner 1965, JCP 42

return MultiCompartmentModel([G1Ball()])

zeppelin() A2

Axially symmetric Gaussian (DTI-like, single fascicle).

Basser et al. 1994, Biophys J 66

return MultiCompartmentModel([G2Zeppelin()])

temporal_zeppelin() A3

Anisotropic compartment with structural-disorder time dependence.

Novikov et al. 2019, NMR Biomed 32

return MultiCompartmentModel([G3TemporalZeppelin()])

Two-compartment white matter

ball_and_stick() B1

Isotropic Ball + zero-radius Stick (intra-axonal).

Behrens et al. 2003, MRM 50

return MultiCompartmentModel([C1Stick(), G1Ball()])

ball_and_zeppelin() B2

Isotropic Ball + anisotropic Zeppelin (tissue DTI tensor).

Panagiotaki et al. 2012, NeuroImage 59

return MultiCompartmentModel([G2Zeppelin(), G1Ball()])

stick_tortuous_zeppelin() B3

Intra-axonal Stick + tortuous extra-axonal Zeppelin.

Novikov et al. 2019, NMR Biomed 32

mcm = MultiCompartmentModel([C1Stick(), G2Zeppelin()])
mcm.set_tortuous_parameter(          # must come before set_equal_parameter
    'G2Zeppelin_1_lambda_perp',
    'C1Stick_1_lambda_par',
    'partial_volume_0',
    'partial_volume_1',
)
mcm.set_equal_parameter('C1Stick_1_mu', 'G2Zeppelin_1_mu')
mcm.set_equal_parameter('C1Stick_1_lambda_par', 'G2Zeppelin_1_lambda_par')
return mcm

free_water_elimination() B4

Tissue Zeppelin + fixed free-water Ball (D_iso = 3.0e-9 m²/s).

Pasternak et al. 2009, MRM 62

mcm = MultiCompartmentModel([G2Zeppelin(), G1Ball()])
mcm.set_fixed_parameter('G1Ball_1_lambda_iso', _Dcsf)
return mcm

ivim() B5

IVIM: tissue diffusion + vascular pseudo-diffusion.

Le Bihan et al. 1988, Radiology 161

mcm = MultiCompartmentModel([G1Ball(), G1Ball()])
mcm.set_fixed_parameter('G1Ball_2_lambda_iso', 7e-9)
mcm.set_parameter_optimization_bounds('G1Ball_1_lambda_iso', [0.5e-9, 6e-9])
return mcm

Orientation-dispersion

noddi() C1

NODDI: Watson-dispersed Stick + tortuous Zeppelin + CSF Ball.

Zhang et al. 2012, NeuroImage 61

bundle = SD1WatsonDistributed(models=[C1Stick(), G2Zeppelin()])
bundle.set_tortuous_parameter(       # tortuosity before set_equal
    'G2Zeppelin_1_lambda_perp',
    'G2Zeppelin_1_lambda_par',
    'partial_volume_0',
)
bundle.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par')
bundle.set_fixed_parameter('G2Zeppelin_1_lambda_par', _Da)
mcm = MultiCompartmentModel([bundle, G1Ball()])
mcm.set_fixed_parameter('G1Ball_1_lambda_iso', _Dcsf)
return mcm

bingham_noddi() C2

Bingham-NODDI: Bingham-dispersed Stick + tortuous Zeppelin + CSF Ball.

Tariq et al. 2016, NeuroImage 133

bundle = SD2BinghamDistributed(models=[C1Stick(), G2Zeppelin()])
bundle.set_tortuous_parameter(
    'G2Zeppelin_1_lambda_perp',
    'G2Zeppelin_1_lambda_par',
    'partial_volume_0',
)
bundle.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par')
bundle.set_fixed_parameter('G2Zeppelin_1_lambda_par', _Da)
mcm = MultiCompartmentModel([bundle, G1Ball()])
mcm.set_fixed_parameter('G1Ball_1_lambda_iso', _Dcsf)
return mcm

noddida() C3

NODDIDA: Stick + tortuous Zeppelin + free Ball — all diffusivities free.

Jelescu et al. 2015, NMR Biomed 28

mcm = MultiCompartmentModel([C1Stick(), G2Zeppelin(), G1Ball()])
mcm.set_tortuous_parameter(          # tortuosity before set_equal
    'G2Zeppelin_1_lambda_perp',
    'C1Stick_1_lambda_par',
    'partial_volume_0',
    'partial_volume_1',
)
mcm.set_equal_parameter('C1Stick_1_mu', 'G2Zeppelin_1_mu')
mcm.set_equal_parameter('C1Stick_1_lambda_par', 'G2Zeppelin_1_lambda_par')
return mcm

mcsmt() C4

MC-SMT: Multi-Compartment Spherical Mean Technique.

Kaden et al. 2016, NeuroImage 139

mcm = MultiCompartmentSphericalMeanModel([C1Stick(), G2Zeppelin()])
mcm.set_tortuous_parameter(
    'G2Zeppelin_1_lambda_perp',
    'C1Stick_1_lambda_par',
    'partial_volume_0',
    'partial_volume_1',
)
mcm.set_equal_parameter('C1Stick_1_lambda_par', 'G2Zeppelin_1_lambda_par')
return mcm

Multi-fascicle

two_fascicle_noddi() D1

Two independently oriented Watson-NODDI bundles + shared CSF Ball.

Behrens et al. 2007, NeuroImage 34

bundle1 = SD1WatsonDistributed(models=[C1Stick(), G2Zeppelin()])
bundle1.set_tortuous_parameter(
    'G2Zeppelin_1_lambda_perp', 'G2Zeppelin_1_lambda_par', 'partial_volume_0')
bundle1.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par')
bundle1.set_fixed_parameter('G2Zeppelin_1_lambda_par', _Da)

bundle2 = SD1WatsonDistributed(models=[C1Stick(), G2Zeppelin()])
bundle2.set_tortuous_parameter(
    'G2Zeppelin_1_lambda_perp', 'G2Zeppelin_1_lambda_par', 'partial_volume_0')
bundle2.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par')
bundle2.set_fixed_parameter('G2Zeppelin_1_lambda_par', _Da)

mcm = MultiCompartmentModel([bundle1, bundle2, G1Ball()])
mcm.set_fixed_parameter('G1Ball_1_lambda_iso', _Dcsf)
return mcm

Cylinder / axon diameter

charmed() E1

CHARMED: Callaghan cylinder (restricted) + tortuous Zeppelin (hindered).

Assaf & Basser 2005, NeuroImage 27

cyl  = C3CylinderCallaghanApproximation()
zepp = G2Zeppelin()
mcm  = MultiCompartmentModel([cyl, zepp])
mcm.set_tortuous_parameter(
    'G2Zeppelin_1_lambda_perp',
    'C3CylinderCallaghanApproximation_1_lambda_par',
    'partial_volume_0',
    'partial_volume_1',
)
mcm.set_equal_parameter(
    'C3CylinderCallaghanApproximation_1_mu', 'G2Zeppelin_1_mu')
mcm.set_equal_parameter(
    'C3CylinderCallaghanApproximation_1_lambda_par', 'G2Zeppelin_1_lambda_par')
return mcm

axcaliber() E2

AxCaliber: Gamma-distributed Callaghan cylinders + Zeppelin.

Assaf et al. 2008, MRM 59

gamma_cyl = DD1GammaDistributed([C3CylinderCallaghanApproximation()])
mcm = MultiCompartmentModel([gamma_cyl, G2Zeppelin()])
mcm.set_equal_parameter(
    'DD1GammaDistributed_1_C3CylinderCallaghanApproximation_1_mu',
    'G2Zeppelin_1_mu',
)
return mcm

active_ax() E3

ActiveAx: single-diameter Callaghan cylinder + Zeppelin + free Ball.

Alexander et al. 2010, NeuroImage 52

mcm = MultiCompartmentModel([
    C3CylinderCallaghanApproximation(), G2Zeppelin(), G1Ball()])
mcm.set_fixed_parameter('G1Ball_1_lambda_iso', _Dcsf)
return mcm

Soma / sphere

verdict() F1

VERDICT: Sphere (cell body) + Stick (membrane/vascular) + Ball (EES).

Panagiotaki et al. 2014, Cancer Res 74

return MultiCompartmentModel([
    S4SphereGaussianPhaseApproximation(), C1Stick(), G1Ball()])

sandi() F2

SANDI: Sphere (soma) + Stick (neurite) + Ball (extra-cellular).

Palombo et al. 2020, NeuroImage 215

soma = S4SphereGaussianPhaseApproximation(diffusion_constant=_Din)
mcm  = MultiCompartmentModel([soma, C1Stick(), G1Ball()])
mcm.set_fixed_parameter('C1Stick_1_lambda_par', _Da)
return mcm

impulsed() F3

IMPULSED: Sphere + isotropic Ball (two-compartment, fixed D_in).

Xu et al. 2019, Magn Reson Med

soma = S4SphereGaussianPhaseApproximation(diffusion_constant=_Din)
return MultiCompartmentModel([soma, G1Ball()])

Membrane exchange

nexi() G1

NEXI: Neurite Exchange Imaging — Stick + Zeppelin with Kärger exchange.

Jelescu et al. 2022, NeuroImage 256

stick, zeppelin = C1Stick(), G2Zeppelin()
karger = X0GeneralizedKarger(
    stick, zeppelin,
    parameter_links=[(zeppelin, 'lambda_perp', T1_tortuosity(),
                      [(zeppelin, 'lambda_par'), (None, 'f')])])
return MultiCompartmentModel([karger])

karger_two_compartment() G2

Generic Kärger two-compartment model: Ball + Ball with exchange.

Kärger 1985, Adv Colloid Interface Sci 23

return MultiCompartmentModel([X0GeneralizedKarger(G1Ball(), G1Ball())])

fexi() G3

FEXI: Filter EXchange Imaging — two isotropic pools with exchange.

Lasič et al. 2011, MRM 66

slow = G1Ball()
fast = G1Ball()
mcm  = MultiCompartmentModel([X0GeneralizedKarger(slow, fast)])
mcm.set_fixed_parameter('X0GeneralizedKarger_1_G1Ball_2_lambda_iso', 2.0e-9)  # fast pool D
return mcm

sandix() G4

SANDIX: SANDI with exchange between soma (sphere) and extracellular (Ball).

SANDI (Palombo 2020) + Kärger 1985

soma  = S4SphereGaussianPhaseApproximation(diffusion_constant=_Din)
extra = G1Ball()
mcm   = MultiCompartmentModel([X0GeneralizedKarger(soma, extra), C1Stick()])
mcm.set_fixed_parameter('C1Stick_1_lambda_par', _Da)
return mcm

exchange_impulsed() G5

EXCHANGE: IMPULSED + transcytolemmal Kärger exchange (tumour).

Shi et al. 2025, Magn Reson Imaging

soma  = S4SphereGaussianPhaseApproximation(diffusion_constant=_Din)
extra = G1Ball()
return MultiCompartmentModel([X0GeneralizedKarger(soma, extra)])

Time-dependent

temporal_zeppelin_model() H1

Temporal Zeppelin + free Ball: Standard Model with structural disorder.

Novikov et al. 2019, NMR Biomed 32

mcm = MultiCompartmentModel([G3TemporalZeppelin(), G1Ball()])
mcm.set_fixed_parameter('G1Ball_1_lambda_iso', _Dcsf)
return mcm

Relaxometry (multi-TE)

mte_ball_stick() I1

Multi-TE Ball-and-Stick with per-compartment T2 relaxation.

Gong et al. 2020, NeuroImage 217

mcm = MultiCompartmentModel([C1Stick(), G1Ball()])
return mcm   # T2 on both compartments is free by default

mte_noddi() I2

MTE-NODDI: NODDI extended with per-compartment T2 relaxation.

Gong et al. 2020, NeuroImage 217

bundle = SD1WatsonDistributed(models=[C1Stick(), G2Zeppelin()])
bundle.set_tortuous_parameter(
    'G2Zeppelin_1_lambda_perp', 'G2Zeppelin_1_lambda_par', 'partial_volume_0')
bundle.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par')
bundle.set_fixed_parameter('G2Zeppelin_1_lambda_par', _Da)
mcm = MultiCompartmentModel([bundle, G1Ball()])
mcm.set_fixed_parameter('G1Ball_1_lambda_iso', _Dcsf)
return mcm   # T2 on Stick and Zeppelin inside bundle are free parameters

mte_sandi() I3

MTE-SANDI: SANDI with per-compartment T2 relaxation.

ISMRM 2023 abstract #0766

soma = S4SphereGaussianPhaseApproximation(diffusion_constant=_Din)
mcm  = MultiCompartmentModel([soma, C1Stick(), G1Ball()])
mcm.set_fixed_parameter('C1Stick_1_lambda_par', _Da)
return mcm   # T2 on Stick and Ball compartments are free; soma has no T2 param

wmti() I4

WMTI: White Matter Tract Integrity — biophysical Standard Model structure.

Fieremans et al. 2011, NeuroImage 58

mcm = MultiCompartmentModel([C1Stick(), G2Zeppelin()])
mcm.set_tortuous_parameter(
    'G2Zeppelin_1_lambda_perp',
    'C1Stick_1_lambda_par',
    'partial_volume_0',
    'partial_volume_1',
)
mcm.set_equal_parameter('C1Stick_1_mu', 'G2Zeppelin_1_mu')
mcm.set_equal_parameter('C1Stick_1_lambda_par', 'G2Zeppelin_1_lambda_par')
return mcm

noddida_mte() I5

NODDIDA-MTE: unconstrained NODDIDA with per-compartment T2.

Jelescu 2015 + Gong 2020

mcm = MultiCompartmentModel([C1Stick(), G2Zeppelin(), G1Ball()])
mcm.set_tortuous_parameter(
    'G2Zeppelin_1_lambda_perp',
    'C1Stick_1_lambda_par',
    'partial_volume_0',
    'partial_volume_1',
)
mcm.set_equal_parameter('C1Stick_1_mu', 'G2Zeppelin_1_mu')
mcm.set_equal_parameter('C1Stick_1_lambda_par', 'G2Zeppelin_1_lambda_par')
return mcm   # T2 on all three compartments are free parameters

mte_impulsed() I6

MTE-IMPULSED: IMPULSED with per-compartment T2 relaxation.

Jiang et al. 2025, MRM

return MultiCompartmentModel([S4SphereGaussianPhaseApproximation(), G1Ball()])