Skip to content

Utilities API

Frequently used math, visualization, and export helpers pulled from their docstrings. Diffusion summaries and NIfTI exporters live in dmriutils; coordinate transforms and posterior diagnostics are grouped below.

Diffusion helpers

dmriutils

ssfp_signal_fn

ssfp_signal_fn(adc: ArrayLike, qval: ArrayLike, E1: ArrayLike, E2: ArrayLike, sa: ArrayLike, ca: ArrayLike, TR: ArrayLike, diff_grad_dur: ArrayLike, S0: ArrayLike = 1.0)

Numerically-stable SSFP diffusion-attenuation signal.

Identical output to ssfp_signal_fn, but robust for very large ADCs. Works with scalars or arbitrary-shaped arrays and remains JIT/grad-safe.

fit_diffusion_tensor_linearized

fit_diffusion_tensor_linearized(logS: Array, bvals: Array, bvecs: Array) -> ArrayLike

Linearized fit of the diffusion tensor.

Parameters:

Name Type Description Default
logS ArrayLike

Signal in log-space.

required
bvals ArrayLike

Bvalues.

required
bvecs ArrayLike

Bvectors.

required

Returns:

Name Type Description
Array ArrayLike

description

cart2sph

cart2sph(x: ArrayLike, y: ArrayLike | None = None, z: ArrayLike | None = None) -> Array | tuple[Array, Array]

Convert Cartesian coordinates to spherical coordinates.

Accepts either a single stacked array (..., 3) / (3, ...) or three separate components. Returns a stacked output when the input is stacked, otherwise a tuple (theta, phi).

sph2cart

sph2cart(theta: ArrayLike, phi: ArrayLike | None = None) -> Array | tuple[Array, Array, Array]

Convert spherical coordinates to Cartesian coordinates.

Accepts stacked [..., 2] / (2, ...) inputs or two separate arrays. Returns a stacked output when the input is stacked, otherwise a tuple (x, y, z).

normalize_bvecs

normalize_bvecs(bvecs: ArrayLike) -> ArrayLike

Normalize b-vectors to unit length.

compute_fa

compute_fa(D: ArrayLike) -> ArrayLike

Compute fractional anisotropy (FA) from a diffusion tensor.

compute_md

compute_md(D: ArrayLike) -> ArrayLike

Compute mean diffusivity (MD) from a diffusion tensor.

compute_rd

compute_rd(D: ArrayLike) -> ArrayLike

Compute radial diffusivity (RD) from a diffusion tensor.

compute_ad

compute_ad(D: ArrayLike) -> ArrayLike

Compute axial diffusivity (AD) from a diffusion tensor.

rotation_matrix_100_to_theta_phi

rotation_matrix_100_to_theta_phi(theta, phi)

Generates a rotation matrix that rotates from the x-axis (1, 0, 0) to an other position on the unit sphere.

Parameters

theta : float, inclination of polar angle of main angle mu [0, pi]. phi : float, polar angle of main angle mu [-pi, pi].

Returns

R : array, shape (3 x 3) Rotation matrix.

rotation_matrix_100_to_xyz

rotation_matrix_100_to_xyz(x, y, z)

Generates a rotation matrix that rotates from the x-axis (1, 0, 0) to an other position in Cartesian space.

Parameters

x, y, z : floats, position in Cartesian space.

Returns

R : array, shape (3 x 3) Rotation matrix.

rotation_matrix_100_to_theta_phi_psi

rotation_matrix_100_to_theta_phi_psi(theta, phi, psi)

Generates a rotation matrix that rotates from the x-axis (1, 0, 0) to an other position in Cartesian space, and rotates about its axis.

Parameters

theta : float, inclination of polar angle of main angle mu [0, pi]. phi : float, polar angle of main angle mu [-pi, pi]. psi : float, angle in radians of the bingham distribution around mu [0, pi].

Returns

R : array, shape (3 x 3) Rotation matrix.

rotation_matrix_around_100

rotation_matrix_around_100(psi)

Generates a rotation matrix that rotates around the x-axis (1, 0, 0).

Parameters

psi : float, euler angle [0, pi].

Returns

R : array, shape (3 x 3) Rotation matrix.

make_dyads

make_dyads(theta_samples: Array, phi_samples: Array, percentile: float = None) -> tuple[Array, Array]

Uses fibre orientation samples (in spherical coordinates) from the posterior to estimate the mean fibre orientation (in cartesian coordinates [x,y,z]) and the uncertainty (dispersion) around it.

Parameters:

Name Type Description Default
theta_samples Array

Array of inclination angles

required
phi_samples Array

Array of azimuthal angles

required
percentile float

Optional percentile for dispersion calculation

None

Returns:

Name Type Description
tuple tuple[Array, Array]

(v, disp) where v is the mean orientation and disp is the dispersion

export_nifti

export_nifti(data: ArrayLike, orig_data: Any, output_path: str, name: str, volume_slice: tuple[slice, ...] | None = None) -> None

Save an array to NIfTI, preserving affine/slices from the source image.

Transforms and math

transform

normal_to_dirichlet module-attribute

normal_to_dirichlet: ArrayLike = jax.jit(normal_to_dirichlet)

eps_mask

eps_mask(mask: ndarray) -> ndarray

normal_to_dirichlet_fwd

normal_to_dirichlet_fwd(alpha, eps, mask)

normal_to_dirichlet_bwd

normal_to_dirichlet_bwd(res, g: ArrayLike)

We return gradients only where eps actually matters (eps_mask(mask)==True). Everywhere else grad_eps is forced to 0. No gradient for alpha or mask (consistent with your earlier design).

dirichlet_to_normal

dirichlet_to_normal(alpha: ArrayLike, pi: ArrayLike, mask: ArrayLike | None = None) -> ArrayLike

shm

real_sh_descoteaux_from_index_jax

real_sh_descoteaux_from_index_jax(m_values: ArrayLike, l_values: ArrayLike, theta: ArrayLike, phi: ArrayLike, *, sh_order_max: int = 4, legacy: bool = True) -> ArrayLike

Compute real spherical harmonics using the Descoteaux basis.

This function implements the real spherical harmonics basis as described in Descoteaux et al. (2007). The basis is commonly used in diffusion MRI for representing orientation distribution functions (ODFs).

Parameters:

Name Type Description Default
m_values ArrayLike

Array of order values (m) for spherical harmonics.

required
l_values ArrayLike

Array of degree values (l) for spherical harmonics.

required
theta ArrayLike

Array of polar angles (colatitude) in radians.

required
phi ArrayLike

Array of azimuthal angles in radians.

required
sh_order_max int

Maximum order of spherical harmonics (default: 4).

4
legacy bool

If True, uses absolute value of m_values as in legacy implementations. If False, uses m_values directly (default: True).

True

Returns:

Type Description
ArrayLike

Array of real spherical harmonics values.

Notes
  • The basis is normalized according to the Descoteaux convention.
  • For m > 0, the imaginary part is used; for m ≤ 0, the real part is used.
  • The basis is scaled by sqrt(2) for m ≠ 0 to ensure orthonormality.

real_sh

real_sh(sh_order_max: int, theta: ArrayLike, phi: ArrayLike, *, full_basis: bool = False, legacy: bool = True) -> tuple[ArrayLike, ArrayLike, ArrayLike]

Compute real spherical harmonics for a given maximum order.

This function generates real spherical harmonics up to a specified maximum order for given angular coordinates. It uses the Descoteaux basis and supports both full and symmetric basis sets.

Parameters:

Name Type Description Default
sh_order_max int

Maximum order of spherical harmonics.

required
theta ArrayLike

Array of polar angles (colatitude) in radians.

required
phi ArrayLike

Array of azimuthal angles in radians.

required
full_basis bool

If True, returns the full basis including negative m values. If False, returns only the symmetric part (default: False).

False
legacy bool

If True, uses legacy implementation with absolute m values. If False, uses direct m values (default: True).

True

Returns:

Type Description
ArrayLike

Tuple containing:

ArrayLike
  • Array of real spherical harmonics values
ArrayLike
  • Array of m values (order)
tuple[ArrayLike, ArrayLike, ArrayLike]
  • Array of l values (degree)
Notes
  • The function uses JAX's vmap for efficient vectorization.
  • The basis is normalized according to the Descoteaux convention.
  • The returned arrays are squeezed to remove unnecessary dimensions.

viz

sphere_default module-attribute

sphere_default = get_sphere(name='symmetric724')

orthoview_quiver

orthoview_quiver(data, fractions, colors=None, step=1, downsample_factor=1, slider_step=10, heatmap_quality=1.0, simplified_ui=False, precision=float32, colorscale='gray', arrow_scale=1.0, arrow_width=1, height=None, width=None, show_all_channels=True)

Orthogonal slice views of a volume with fibre-direction arrows overlaid.

Produces compact HTML: the downsampling, quality and precision options below trade rendering fidelity for file size, which matters in notebooks.

Parameters:

Name Type Description Default
data

5D numpy array (x, y, z, channels, 3) of vector data

required
fractions

Fraction weights for each channel (x, y, z, channels)

required
colors

List of colors for vector arrows

None
step

Step size for vector arrow sampling

1
downsample_factor

Factor to downsample data by

1
slider_step

Step size for slice sliders

10
heatmap_quality

Factor to reduce heatmap resolution (0.5 = 50% of original)

1.0
simplified_ui

Whether to use simplified UI with fewer controls

False
precision

Data precision for internal calculations ('float32', 'float16', or 'int8')

float32
colorscale

Colorscale for the background heatmap

'gray'
arrow_scale

Scale factor for vector arrows

1.0
arrow_width

Width of the vector arrows

1
height

Height of the figure in pixels

None
width

Width of the figure in pixels

None
show_all_channels

Whether to show all channels simultaneously (True) or use dropdown selector (False)

True

Returns:

Type Description

plotly figure object

plot_spherical_distribution_polar

plot_spherical_distribution_polar(distribution, n_samples: int = 1000, ax=None, color=None, levels: int = 3, figsize: tuple[float, float] | None = (6, 4), cmap: str = 'viridis', filled: bool = False, contour_kwargs: dict[str, Any] | None = None, show_axis_labels: bool = True, title: str | None = 'Spherical Distribution PDF')

Plot spherical distribution in polar coordinates.

Parameters:

Name Type Description Default
distribution

Spherical distribution object with pdf and sample methods

required
n_samples int

Number of samples to generate

1000
ax

Matplotlib axis to plot on

None
color

Backwards compatible alias for cmap

None
levels int

Number of contour levels

3
figsize tuple[float, float] | None

Figure size when creating a new axis

(6, 4)
cmap str

Matplotlib colormap name

'viridis'
filled bool

Use filled contours instead of lines

False
contour_kwargs dict[str, Any] | None

Additional kwargs forwarded to tricontour/tricontourf

None
show_axis_labels bool

Whether to draw axis labels and ticks

True
title str | None

Title text (set to None to skip)

'Spherical Distribution PDF'

Returns:

Type Description

Tuple of (Figure, Axes)

plot_spherical_distribution_cartesian

plot_spherical_distribution_cartesian(distribution, n_samples: int = 1000, sphere=None, ax=None, figsize: tuple[float, float] | None = (6, 6), cmap: str = 'viridis', vertex_kwargs: dict[str, Any] | None = None, show_samples: bool = True, sample_kwargs: dict[str, Any] | None = None, add_colorbar: bool = True, colorbar_kwargs: dict[str, Any] | None = None, title: str | None = 'Spherical Distribution PDF')

Plot spherical distribution in Cartesian coordinates.

Parameters:

Name Type Description Default
distribution

Spherical distribution object with pdf and sample methods

required
n_samples int

Number of samples to generate

1000
sphere

Sphere object for vertices

None
ax

Matplotlib axis to plot on

None
figsize tuple[float, float] | None

Figure size for new axes

(6, 6)
cmap str

Colormap for pdf-colored vertices

'viridis'
vertex_kwargs dict[str, Any] | None

Extra kwargs forwarded to the pdf scatter

None
show_samples bool

Whether to overlay Monte Carlo samples

True
sample_kwargs dict[str, Any] | None

Extra kwargs forwarded to the samples scatter

None
add_colorbar bool

Whether to draw a colorbar for the pdf values

True
colorbar_kwargs dict[str, Any] | None

Extra kwargs forwarded to fig.colorbar

None
title str | None

Title text (None to skip)

'Spherical Distribution PDF'

Returns:

Type Description

Tuple of (Figure, Axes)

plot_spherical_distribution_fod

plot_spherical_distribution_fod(distribution, ax=None, alpha: float = 0.8, figsize: tuple[float, float] | None = (5, 5), cmap: str | None = 'viridis', surface_kwargs: dict[str, Any] | None = None, hide_axes: bool = True)

Plot spherical distribution as a fiber orientation distribution (FOD).

Parameters:

Name Type Description Default
distribution

Spherical distribution object with pdf and sample methods

required
ax

Matplotlib axis to plot on

None
alpha float

Transparency of the surface

0.8
figsize tuple[float, float] | None

Figure size when creating a new axis

(5, 5)
cmap str | None

Colormap applied to the pdf evaluated on the sphere (set to None for default Matplotlib coloring)

'viridis'
surface_kwargs dict[str, Any] | None

Additional kwargs forwarded to plot_surface

None
hide_axes bool

Remove axis spines/ticks when True

True

Returns:

Type Description

Tuple of (Figure, Axes)

orthoview

orthoview(data, vmin=None, vmax=None, channel_names=None, color_map='gray', downsample_factor=1, slider_step=10, heatmap_quality=1.0, simplified_ui=False, precision=float32, height=None, width=None)

Orthogonal slice views of a scalar volume.

Produces compact HTML: the downsampling, quality and precision options below trade rendering fidelity for file size, which matters in notebooks.

Parameters:

Name Type Description Default
data

3D or 4D numpy array (x, y, z, [channels])

required
vmin

Minimum value for colorscale

None
vmax

Maximum value for colorscale

None
channel_names

Names for channels in dropdown

None
downsample_factor

Factor to downsample data by

1
slider_step

Step size for slice sliders

10
heatmap_quality

Factor to reduce heatmap resolution (0.5 = 50% of original)

1.0
simplified_ui

Whether to use simplified UI with fewer controls

False
precision

Data precision ('float32', 'float16', or 'int8')

float32

Returns:

Type Description

plotly figure object

plot_stereographic_scatter

plot_stereographic_scatter(V, axial=True, angle_step=30, ring_radii=(0.25, 0.5, 0.75, 1.0), s=14, point_alpha=0.9, point_color='orientation', edge=True, ax=None, figsize: tuple[float, float] | None = (5, 5), facecolor: str | None = 'black', frame_color: str = 'white', draw_guides: bool = True)

Scatter-only stereographic plot with better visibility. Args: point_color: "orientation" maps |x|,|y|,|z| to RGB, otherwise any Matplotlib color facecolor: Background color for the stereographic disk (None to keep default) frame_color: Color used for boundary, guides and annotations

Returns:

Type Description

Tuple of (Figure, Axes)

plot_stereographic_contour

plot_stereographic_contour(V, axial=True, angle_step=30, ring_radii=(0.25, 0.5, 0.75, 1.0), bins=128, levels=6, filled=True, cmap='viridis', weights=None, alpha=0.85, ax=None, figsize: tuple[float, float] | None = (5, 5), facecolor: str | None = 'black', frame_color: str = 'white', draw_guides: bool = True, normalize: bool = True)

Plot stereographic density contours for one or more orientation samples.

direction_colour

direction_colour(vectors: ArrayLike, weight: ArrayLike | None = None) -> ndarray

Direction-encoded colour for a field of unit vectors.

The standard dMRI convention: the absolute x/y/z components of a fibre direction become red/green/blue, so left-right tracts read red, anterior- posterior green and superior-inferior blue. Sign is dropped because a fibre orientation is an axis, not an arrow -- v and -v are the same fibre and must get the same colour.

Parameters:

Name Type Description Default
vectors ArrayLike

(..., 3) array of directions; need not be normalised.

required
weight ArrayLike | None

optional (...) array scaling brightness, typically the volume fraction of that fibre. Without it every voxel is fully saturated and noise outside the brain looks like signal.

None

Returns:

Type Description
ndarray

(..., 3) float array in [0, 1].

slice_viewer

slice_viewer(volumes: ArrayLike | Mapping[str, ArrayLike], axis: int = 2, title: str | None = None, height: int = 520, width: int | None = None) -> Figure

Browse volumes slice by slice, as a small self-contained figure.

An alternative to :func:orthoview for looking at output maps. Each slice is embedded once as a compressed image rather than as a JSON float array, which is roughly 16x smaller for a typical volume; a slider steps through slices and, given several volumes, a dropdown switches between them.

The trade-off is quantisation: slices are mapped to 256 levels per channel for display, so this is a viewer, not a way to read exact voxel values. Each scalar volume is scaled by its own min/max.

Parameters:

Name Type Description Default
volumes ArrayLike | Mapping[str, ArrayLike]

a 3-D array, or a mapping of name -> array. Each is either a 3-D scalar volume (trailing singleton axis accepted and squeezed) or a 4-D (X, Y, Z, 3) colour volume in [0, 1], as produced by :func:direction_colour.

required
axis int

axis to slice along (0=sagittal, 1=coronal, 2=axial).

2
title str | None

figure title.

None
height int

figure height in pixels.

520
width int | None

figure width in pixels, or None to let plotly decide.

None

Returns:

Type Description
Figure

A plotly figure.

save_viewer

save_viewer(figure: Figure, destination: str | Path, title: str = 'dmri viewer') -> Path

Write a slice viewer as a standalone dark HTML page.

Parameters:

Name Type Description Default
figure Figure

a figure from :func:slice_viewer.

required
destination str | Path

path to write.

required
title str

browser tab title.

'dmri viewer'

Returns:

Type Description
Path

The path written, as a :class:pathlib.Path.