Skip to content

brainhops.io.base.minc

The shared MINC-reading machinery.

MINC is the volume format of the Montreal Neurological Institute (MNI) and of the MINC toolkit. It comes in two containers, both with the extension .mnc:

  • MINC1 is a NetCDF classic file (magic CDF\x01, or CDF\x02 for the 64-bit offset variant). The voxels are the variable image, whose dimensions name the axes, and each spatial dimension is described by a variable of the same name.
  • MINC2 is an HDF5 file with a root group /minc-2.0. The voxels are the dataset /minc-2.0/image/0/image, whose attribute dimorder names the axes, and each dimension is described by a dataset under /minc-2.0/dimensions.

In both, the dimensions are listed slowest first (C order), in any order: zspace, yspace, xspace is common (transverse slices), but sagittal or coronal orders are just as valid. A dimension is described by its start, its step (which may be negative), its direction_cosines and its units. The world coordinates of a voxel are

world = sum_d (start_d + index_d * step_d) * direction_cosines_d

over the spatial dimensions xspace, yspace and zspace, in a world space whose axes run left-to-right, posterior-to-anterior and inferior-to-superior (RAS), in millimetres by default. A dimension without direction cosines runs along its own world axis.

Integer voxels are scaled to real values through image-min and image-max, which map the valid range of the type to real values, possibly with one scaling per slice.

The headers and the voxels are read with nibabel (nibabel.minc1, nibabel.minc2); MINC2 needs h5py, imported only when a MINC2 file is read. nibabel cannot write MINC, so neither can brainhops.

Limitations, inherited from nibabel

Dimensions with irregular spacing (spacing = "irregular") and dimensions that have no describing variable (such as MINC's vector_dimension, used for RGB volumes and displacement grids) are not supported, nor is a volume without image-min and image-max (which the MINC library always writes).

Classes

MincDimension magic

MincDimension(
    name: str,
    length: int,
    start: float | None = None,
    step: float | None = None,
    direction_cosines: tuple[float, ...] | None = None,
    units: str | None = None,
)

Bases: Magic

One dimension of a MINC volume, as its header describes it.

The attributes the file does not record are None; the properties give MINC's defaults instead.

Attributes

name instance-attribute
name: str

The MINC name of the dimension ("xspace", "time", ...).

length instance-attribute
length: int

The number of samples along the dimension.

start class-attribute instance-attribute
start: float | None = None

The world coordinate of the first sample, along the direction cosines (MINC's default is 0).

step class-attribute instance-attribute
step: float | None = None

The distance between two samples, possibly negative (MINC's default is 1).

direction_cosines class-attribute instance-attribute
direction_cosines: tuple[float, ...] | None = None

The world direction of the dimension, for a spatial one (MINC's default is its own world axis).

units class-attribute instance-attribute
units: str | None = None

The unit of start and step, as written in the file.

is_spatial property
is_spatial: bool

Whether the dimension is one of xspace, yspace, zspace.

origin property
origin: float

start, or 0 when the file does not record it.

spacing property
spacing: float

step, or 1 when the file does not record it.

cosines property
cosines: tuple[float, float, float]

direction_cosines, or the dimension's own world axis.

MincParser magic

MincParser(
    dimensions: tuple[MincDimension, ...] = (),
    _source: _Source | None = None,
)

Bases: DataModelBase, BinaryFileParser

Base class for objects that are encoded by a MINC1 or MINC2 file.

It holds the dimensions of the volume ([dimensions][brainhops.io.base.minc.MincParser.dimensions]), in the order the file stores them (slowest first), and reads the voxels on first access, scaled to real values, from the file it was loaded from. The voxel coordinate system and the voxel-to-world matrix are those of the array in F order, i.e. with the axes reversed, so that the fastest-varying dimension comes first.

A concrete format sets VERSION (1 or 2) and is only recognised in files of that version. A class with no version reads both, and returns an object of the matching class among its VARIANTS.

Attributes

VERSION class-attribute
VERSION: int | None = None

The MINC version read by this class, or None for both.

VARIANTS class-attribute
VARIANTS: tuple[type, ...] = ()

The classes that a class with no VERSION hands files to.

version property
version: int | None

The MINC version of the file (1 or 2).

shape property
shape: tuple[int, ...] | None

The shape of the volume in F order (fastest dimension first).

vox2world property
vox2world: ndarray | None

The (4, 4) voxel-to-world (RAS) matrix of the F-ordered array.

Its columns follow the spatial axes of system (the non-spatial ones, such as time, are skipped). It is None unless the volume has the three spatial dimensions.

data property writable
data: ArrayProtocol | None

The voxels in F order, scaled to real values, read on first access and cached, unless set explicitly.

system property writable
system: CoordinateSystem | None

The voxel coordinate system, in F order, derived from the dimensions unless set explicitly.

PREFIXES class-attribute
PREFIXES: tuple[str, ...] = ()

Filename prefixes required by this parser, e.g. ("y_", "iy_").

An empty tuple means "no constraint". A parser that constrains the prefix is more specific than one that does not, and wins ties.

Declaring EXTENSIONS and PREFIXES separately states the cross-product implicitly, which is how these conventions actually work: SPM's four names are {y_, iy_} x {.nii, .nii.gz}.

PRIORITY class-attribute
PRIORITY: int = 0

Explicit tie-breaker, consulted only when specificity cannot decide. Higher wins. Leave at 0 unless two parsers genuinely collide.

Methods:

sniff_filename classmethod
sniff_filename(
    filename: FilenameLike,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> float

Score a file by its content (a MINC2 file is opened by name, so that only its header is read).

sniff_fileobj classmethod
sniff_fileobj(
    file: IO,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> float

Score how confident the class is that an open file object holds a MINC file of its version, from its content.

A MINC1 file is a NetCDF file (gzipped or not) whose header names a MINC spatial dimension and an image variable; a NetCDF file that does not is only weakly accepted. A MINC2 file is an HDF5 file with a /minc-2.0 group.

sniff_bytes classmethod
sniff_bytes(
    content: bytes,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> float

Score how confident the class is that bytes hold a MINC file of its version.

from_filename classmethod
from_filename(filename: FilenameLike, **kwargs) -> Self

Build the object from a MINC file.

Only the header is read: the voxels are read from the file, by name, on first access. A file that is not local, or that is gzipped, is read into memory first.

from_fileobj classmethod
from_fileobj(file: IO, **kwargs) -> Self

Build the object from an open MINC file object (gzipped or not), which is read into memory.

from_bytes classmethod
from_bytes(content: bytes, **kwargs) -> Self

Build the object from the bytes of a MINC file (gzipped or not).

sniff classmethod
sniff(
    file: FileOrContentLike,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> float

Determine if the given file is of the type that this parser can handle.

Parameters:

Name Type Description Default
file FileOrContentLike

The file to sniff.

required
error bool | type[Exception]

If not False, raise an error if the file cannot be sniffed.

False
**kwargs

Parser-specific options.

{}

Returns:

Type Description
float

Confidence that the file is of this type, in [0, 1].

sniff_file classmethod
sniff_file(
    file: FileLike,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> float

Determine if the given file is of the type that this parser can handle.

Parameters:

Name Type Description Default
file FileLike

The file to sniff.

required
error bool | type[Exception]

If not False, raise an error if the file cannot be sniffed.

False
**kwargs

Parser-specific options.

{}

Returns:

Type Description
float

Confidence that the file is of this type, in [0, 1].

sniff_content classmethod
sniff_content(
    content: ContentLike,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> float

Determine if the given content is of the type that this parser can handle.

Parameters:

Name Type Description Default
content ContentLike

The content to sniff.

required
error bool | type[Exception]

If not False, raise an error if the content cannot be sniffed.

False
**kwargs

Parser-specific options.

{}

Returns:

Type Description
float

Confidence that the content is of this type, in [0, 1].

sniff_text classmethod
sniff_text(
    text: str,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> float

Determine if the given text is of the type that this parser can handle.

Parameters:

Name Type Description Default
text str

The text to sniff.

required
error bool | type[Exception]

If not False, raise an error if the content cannot be sniffed.

False
**kwargs

Parser-specific options.

{}

Returns:

Type Description
float

Confidence that the text is of this type, in [0, 1].

sniff_lines classmethod
sniff_lines(
    lines: Iterable[str],
    error: bool | Type[Exception] = False,
    **kwargs,
) -> float

Determine if the given lines are of the type that this parser can handle.

Parameters:

Name Type Description Default
lines Iterable[str]

The lines to sniff.

required
error bool | type[Exception]

If not False, raise an error if the content cannot be sniffed.

False
**kwargs

Parser-specific options.

{}

Returns:

Type Description
float

Confidence that the lines is of this type, in [0, 1].

sniff_line classmethod
sniff_line(
    line: str,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> float

Determine if the given line is of the type that this parser can handle.

Parameters:

Name Type Description Default
line str

The line to sniff.

required
error bool | type[Exception]

If not False, raise an error if the content cannot be sniffed.

False
**kwargs

Parser-specific options.

{}

Returns:

Type Description
float

Confidence that the line is of this type, in [0, 1].

load classmethod
load(other: FileOrContentLike, **kwargs) -> Self

Build an object from a file (path, file-like object or iterable of lines).

This is the generic front door to the from_* family: it looks at what it was handed and calls the right one.

A str is always a path, whether or not the file exists, so a missing file raises FileNotFoundError whichever way its path was spelled. Text held in memory is read with from_text or from_content.

Parameters:

Name Type Description Default
other FileOrContentLike

Input file, or its content.

required
**kwargs

Parser-specific options.

{}

Returns:

Type Description
obj

The parsed object.

Raises:

Type Description
ParserExistsError

If other is a path to a file that does not exist. It is a FileNotFoundError.

from_spec classmethod
from_spec(spec: SourceSpec, **kwargs) -> Self

Build an object from an unqualified structured source.

from_file classmethod
from_file(file: FileLike, **kwargs) -> Self

Build an object from a file (path or file-like object).

Parameters:

Name Type Description Default
file FileLike

The file to parse.

required
**kwargs

Parser-specific options.

{}

Returns:

Type Description
obj

The parsed object.

from_content classmethod
from_content(content: ContentLike, **kwargs) -> Self

Build an object from a file content (bytes, str, or iterable of lines).

Parameters:

Name Type Description Default
content ContentLike

The content to parse.

required
**kwargs

Parser-specific options.

{}

Returns:

Type Description
obj

The parsed object.

from_text classmethod
from_text(text: str, **kwargs) -> Self

Build an object from a text representation of a file.

Parameters:

Name Type Description Default
text str

The text to parse.

required
**kwargs

Parser-specific options.

{}

Returns:

Type Description
obj

The parsed object.

from_lines classmethod
from_lines(lines: Iterable[str], **kwargs) -> Self

Build an object from an iterable of lines (e.g., the content of a file).

Parameters:

Name Type Description Default
lines Iterable[str]

The lines to sniff.

required
**kwargs

Parser-specific options.

{}

Returns:

Type Description
obj

The parsed object.

from_line classmethod
from_line(line: str, **kwargs) -> Self

Build an object from a single line of text.

Parameters:

Name Type Description Default
line str

The line to parse.

required
**kwargs

Parser-specific options.

{}

Returns:

Type Description
obj

The parsed object.

from_dict classmethod
from_dict(other: Mapping, *args, **kwargs) -> Self

Create an instance of the class from a dictionary-like object.

Only keys in the dictionary that match keyword-like fields of this class, or the keywords its constructor takes without storing them (its InitVars, such as the matrix= of an Affine), will be used. Other keys are ignored, but see from_other, which refuses them.

Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.

A key naming a field that this class fixes (a field that cannot be passed to its constructor) is checked instead of used: a dictionary that sets it to anything other than None or the value of this class is refused with a ValueError.

from_instance classmethod
from_instance(other: Self, *args, **kwargs) -> Self

Create an instance of the class from an instance of a similar class.

Only attributes of the other instance that match keyword-like fields of this class will be used. An attribute that is None is unset, and leaves the default of this class in place.

Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.

Unless the other instance is already an instance of this class, an attribute naming a field that this class fixes (a field that cannot be passed to its constructor) is checked instead of used: an instance that sets it to anything other than None or the value of this class is refused with a ValueError. A generic Axis whose orientation is right-to-left, for example, cannot be read as a LeftToRightAxis.

from_other classmethod
from_other(other: Any, *args, **kwargs) -> Self

Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.

A similar class is this class or one of its parents within the data model, or another member of a polymorphic family this class belongs to: calling a polymorphic class such as Axis builds the subclass its arguments select, so a "generic" axis is usually an instance of a sibling (a RightToLeftAxis, a TimeAxis) rather than of a parent. Any other object, including an instance of a parent that is not a data model (such as a plain object), is passed to the constructor.

Unlike from_dict, a dictionary with a key that matches no field of this class is refused with a TypeError naming the keys, so that a misspelt key is not silently dropped.

Functions:

minc_version

minc_version(head: bytes) -> int | None

The MINC version that the leading bytes of a file suggest: 1 for a NetCDF classic file, 2 for an HDF5 file, None otherwise.

An HDF5 file is only a MINC2 candidate: it must still hold a /minc-2.0 group.