Conventions#
The coordinates, units, orders and bases Larmor uses, so that you can check your data against them. Each section names the functions and classes that implement it.
Coordinates and spaces#
Term |
Meaning |
|---|---|
Voxel coordinates |
Indices (i, j, k) along the image’s voxel axes, counted from 0. Index (i, j, k) is the centre of that voxel. |
World coordinates |
Scanner coordinates in mm, RAS+: x increases to the subject’s right, y to anterior, z to superior. |
Affine |
The (4, 4) float64 matrix that maps voxel indices to world coordinates. Its last row is [0, 0, 0, 1]. |
Orientation |
For each voxel axis, the world direction it is closest to: |
Every Volume and Grid carries its affine; the voxel sizes are
the lengths of its first three columns. The points of a Tractogram, the positions of
Seeds, the directions of a GradientTable and the
viewer’s cursor are all in world coordinates, whatever the file’s own convention.
Reading the affine. read_nifti() takes the sform when sform_code > 0, otherwise
the qform when qform_code > 0 (a negative qfac in pixdim[0] flips the third axis), otherwise
diag(pixdim[1], pixdim[2], pixdim[3], 1). xyzt_units is ignored: lengths are taken as mm.
read_mif() builds the affine from the header’s transform and vox, and returns the
axes in the order of dim whatever the layout (the MRtrix3 strides) on disk, reversed axes included.
Writing the affine. write_nifti() writes the affine exactly into the sform and its
closest rotation into the qform, both with code 1 (scanner). write_mif() writes
layout: +0,+1,+2 (x fastest) and the affine as transform and vox.
Orientation. Volume.orientation gives the orientation codes.
to_orientation() and to_closest_canonical() (or
lar convert --to-ras) only permute and flip voxel axes and update the affine, so every voxel keeps its world
position and nothing is resampled. Reorienting an image never changes its gradient table, which is in world
coordinates.
Masks. A mask given as a Volume to DTIModel.fit,
DKIModel.fit, SDModel.fit,
estimate_wm_rf() or denoise_mppca() must be on the image’s grid. A mask
stored in another orientation of that grid (axes permuted or flipped, the same voxels in the world) is reoriented
to the image’s, with a warning; a mask on another grid is refused. A mask given as an array must have the image’s
spatial shape. Nonzero values are inside.
Gradient tables#
A GradientTable holds one b-value and one direction per volume, in the order of the
volumes.
Item |
Convention |
|---|---|
b-values |
s/mm^2 |
Directions |
Unit vectors in world coordinates (RAS+) |
Vectors not of unit length |
Made unit length, with b multiplied by the squared length: 0.5 at b=2800 becomes 1 at b=700 |
b=0 volumes |
b at or below |
Shells |
The other b-values, sorted; a gap larger than |
Selecting a shell |
|
b-matrix |
One row per volume: b * (gx^2, 2 gx gy, 2 gx gz, gy^2, 2 gy gz, gz^2), in world coordinates |
The files store the directions in different frames. The frame argument of
read_bvals_bvecs(), write_bvals_bvecs() and load_dwi()
(--bvec-frame on the command line) says which:
File |
Frame |
Python |
|---|---|---|
FSL bvecs, |
The image’s voxel axes (the rotation closest to its affine), with x negated when that rotation’s determinant is positive. Converting needs the image. |
|
bvecs, |
World coordinates, nothing converted |
The same, with |
MRtrix3 gradient file ( |
World coordinates, rows |
|
A bvecs file is read as (3, N) or (N, 3) and written as (3, N); bvals are written as one row. A b-matrix does not
store the sign of a direction, so read_b_matrix() returns each with its first non-zero
component positive.
Spherical harmonics#
FODs are stored as real spherical harmonic (SH) coefficients along the last axis of a 4D image, in the frame of the gradient table: world coordinates. A direction is given by theta, its angle from +z, and phi, its angle around z from +x.
Item |
Convention |
|---|---|
Bases |
|
Coefficient order |
By degree l, then by order m from -l to l |
Symmetric FOD |
Even degrees only: (lmax + 1)(lmax + 2) / 2 coefficients (1, 6, 15, 28, 45 for lmax 0 to 8) |
Asymmetric FOD |
All degrees: (lmax + 1)^2 coefficients (4, 9, 16, 25, …) |
Telling them apart |
By the number of coefficients ( |
Normalisation |
Orthonormal on the sphere. N(l, m) = sqrt((2l + 1) / (4 pi) * (l - |m|)! / (l + |m|)!), and the associated Legendre function P(l, |m|) includes the Condon-Shortley phase |
FOD scale |
The integral over the sphere, c00 * sqrt(4 pi), is the tissue’s signal fraction relative to S0 |
lmax of a fit |
Even and at least 2, 8 by default; lowered by 2 until the highest shell has at least as many volumes as coefficients |
With Y(l, m) = N(l, m) P(l, |m|)(cos theta):
Basis |
m < 0 |
m = 0 |
m > 0 |
|---|---|---|---|
|
sqrt(2) Y(l, m) sin(|m| phi) |
Y(l, 0) |
sqrt(2) Y(l, m) cos(m phi) |
|
sqrt(2) (-1)^m Y(l, m) cos(|m| phi) |
Y(l, 0) |
sqrt(2) Y(l, m) sin(m phi) |
|
|
|
|
An image file does not record its basis, so it is given when an FOD is read (basis= in Python, --basis on the
command line, the FOD’s options in the viewer). SDModel writes symmetric FODs;
find_peaks(), the Tracker, lar sh-convert and the viewer
read both layouts. convert_sh_basis() converts between the bases and
fit_sh() fits coefficients to amplitudes on a set of directions.
The peaks of a symmetric FOD have z >= 0; an asymmetric FOD’s keep their sign. lar peaks writes each peak as its
unit direction times its amplitude, three values per peak along the last axis.
Tractograms#
A Tractogram holds the points of all streamlines as one (P, 3) float32 array in world mm,
and (S + 1,) int64 offsets: streamline s is points[offsets[s]:offsets[s + 1]]. Values per point are in
point_data (first axis P) and values per streamline in streamline_data (first axis S).
File |
Points on disk |
Python |
|---|---|---|
TCK |
World mm, float32, a NaN row after each streamline and an Inf row at the end. No grid, no values. |
|
TRK |
TrackVis voxel mm: mm from the corner of the first voxel, along the axes of the header’s |
|
VTK, |
As stored, taken as world mm. |
|
TSF |
One value per point, in the order of the points, a NaN after each streamline. Paired with its TCK by the header’s |
A TRK file of version 2 is placed by its own vox_to_ras; one of version 1, or without vox_to_ras, needs a
reference grid. A TRK without voxel_order is read as LPS. Writing a TRK needs a reference grid (the reference
argument, or the tractogram’s own), which sets dim, voxel_size, vox_to_ras and voxel_order.
Point order. The Tracker keeps every point it steps to. A streamline tracked
one way starts at its seed. One tracked both ways (the default) runs from the end reached along the seed’s first
direction, through the seed, to the end reached along the opposite direction. Seed files
(read_seeds(), write_seeds()) hold world mm.
See Tractography and Loading and saving data.
Arrays and units in Python#
Data |
Shape |
Units and type |
|---|---|---|
|
(X, Y, Z) or (X, Y, Z, N): voxel axes i, j, k, then the series (DWI volumes, SH coefficients) |
As stored in the file, without the scaling |
|
Scalars |
value = data * slope + intercept; a slope of 0, NaN or Inf means no scaling. |
|
(4, 4) |
float64, voxel indices to world mm |
|
(N,), (N, 3) |
s/mm^2, and unit vectors in world coordinates; float64 |
|
(P, 3), (S + 1,) |
World mm as float32; int64 |
DTI and DKI diffusivities |
(X, Y, Z) |
|
Diffusion tensor |
(X, Y, Z, 6), in the order xx, xy, xz, yy, yz, zz |
mm^2/s, float32, in world coordinates |
Principal eigenvector, peak directions |
(X, Y, Z, 3), (…, P, 3) |
Unit vectors in world coordinates; an eigenvector’s sign is arbitrary |
FODs |
(X, Y, Z, C) |
SH coefficients, see Spherical harmonics |
The viewer#
Item |
Convention |
|---|---|
Display |
Neurological (RAS) by default: the subject’s right on the right of the screen. Radiological (LAS) puts it on the left in the axial and coronal views; the sagittal view is the same in both. Set it with Display convention in Settings, or |
Direction colours |
Red, green and blue are the absolute x, y and z components of a unit direction in world coordinates: red for left-right, green for anterior-posterior, blue for superior-inferior. This holds for direction maps, streamlines (the tangent at each point), peaks and FOD glyphs. A direction map’s channels are clipped to [0, 1], and can be weighted by a map such as FA. |
Crosshair readout |
The cursor’s position in world mm, and the main volume’s name, nearest voxel (i, j, k, with the volume index of a 4D image) and value there, with the scaling applied, interpolated if the volume is shown interpolated. Outside the volume’s grid there is no voxel or value. |
Slice numbers |
Counted from 0, as voxel indices of the main volume. |
See The 2D views and Settings.