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.

The whole thing is built from primitives in a couple dozen lines: three occupancy-gated compartments assembled into one MultiCompartmentModel, sharing one fibre orientation.

from dmipy_fit.core.modeling_framework import MultiCompartmentModel
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

# one Gamma OUTER (fibre) diameter distribution drives both surface factors
gamma_shape, gamma_scale = 2.0, 0.304e-6      # mean outer diameter = shape * scale
f_axon = 0.55                                 # intra-axonal (lumen) volume fraction
S_ext_over_V = exterior_surface_to_volume(f_axon, gamma_shape, gamma_scale)

# each compartment = a diffusion primitive + opt-in occupancy-gated factors (surface relaxivity + T2)
intra  = OccupancyGatedModel(C1Stick(), [
    IntraPoreSurfaceRelaxivity(gamma_shape=gamma_shape,
                               gamma_scale_outer_diameter=gamma_scale,
                               volume_weighted=True),
    TransverseRelaxation()])
extra  = OccupancyGatedModel(G2Zeppelin(), [
    ExteriorSurfaceRelaxivity(S_ext_over_V=S_ext_over_V),
    TransverseRelaxation()])
myelin = OccupancyGatedModel(S1Dot(), [TransverseRelaxation()])   # stuck myelin water (radial D ~ 0)

# assemble into a standard MultiCompartmentModel with one shared fibre orientation
model = MultiCompartmentModel([intra, extra, myelin], S0_global=True)
model.set_equal_parameter('OccupancyGatedModel_1_mu', 'OccupancyGatedModel_2_mu')

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


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()])

The method is the acquisition

IMPULSED is just a sphere and a ball — the cell-size sensitivity comes entirely from the acquisition: a composite scheme mixing OGSE at several frequencies with PGSE, fed as one object (AcquisitionScheme.concatenate([pgse, ogse_50Hz, ogse_100Hz, ...])). Because dmipy is sequence-agnostic, the same two compartments resolve cell diameter with no model change — you just hand them a richer waveform set. Same story for mte_impulsed() (OGSE+PGSE across several TEs).

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)

Per-compartment T2 is a factor, not a built-in parameter

A bare C1Stick()/G1Ball() carries no T2 parameter — diffusion compartments are pure diffusion. To give a compartment its own \(T_2\) (or surface relaxivity) you wrap it in an OccupancyGatedModel with a TransverseRelaxation() factor. The model construction is the opt-in; that is what makes the multi-TE models below fit T2_intra/T2_extra. (These fits also need a multi-echo acquisition — see the surface-relaxivity page.)

mte_ball_stick() I1

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

Gong et al. 2020, NeuroImage 217

from dmipy_fit.signal_models.attenuation import OccupancyGatedModel, TransverseRelaxation
intra = OccupancyGatedModel(C1Stick(), [TransverseRelaxation()])   # exposes ..._T2
extra = OccupancyGatedModel(G1Ball(),  [TransverseRelaxation()])
return MultiCompartmentModel([intra, extra])   # T2_intra, T2_extra now free

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   # wrap each compartment in OccupancyGatedModel([TransverseRelaxation()]) for T2 (see note)

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   # each compartment wrapped in OccupancyGatedModel([TransverseRelaxation()]) for T2 (see note)

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   # each compartment wrapped in OccupancyGatedModel([TransverseRelaxation()]) for T2 (see note)

mte_impulsed() I6

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

Jiang et al. 2025, MRM

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