brainhops.io.base.mgh
The shared MGH/MGZ-reading and MGH/MGZ-writing machinery.
MGH is FreeSurfer's volume format, and MGZ is the same bytes gzipped. A file holds, in order and big-endian:
- a fixed 284-byte header:
version(always 1), the four dimensionswidth, height, depth, nframes, the voxeltype,dof,goodRASFlag, the voxel sizedelta, the direction cosinesMdcand the RAS centre of the volumePxyz_c(seebrainhops.io.base.freesurfer); - the voxels, x fastest, then y, z and frames (F order);
- an optional footer of MRI acquisition parameters:
TR(ms),flip_angle(radians),TE(ms),TI(ms) andFoV; - optional trailing tags (the command line history, the talairach transform file name, ...).
The header and the voxels are read and written with nibabel
(nibabel.freesurfer.mghformat). Two pieces nibabel drops are read
here from the raw bytes, so that a file round-trips:
- the trailing tags, kept verbatim as bytes;
goodRASFlag, whichnibabelsilently resets to 1 (see below).
goodRASFlag
When goodRASFlag is not positive, FreeSurfer ignores the voxel size,
the direction cosines and the centre stored in the header and uses
its defaults instead: 1 mm voxels, coronal LIA direction cosines and
a zero centre. nibabel also resets the voxel size and the centre,
but its default direction cosines are those of an LSP volume, which
disagrees with FreeSurfer (and with nibabel's own tkr matrix). The
readers here follow FreeSurfer.
Attributes
MGH_HEADER_SIZE
module-attribute
Size in bytes of the fixed MGH header; the voxels start right after.
MGH_FOOTER_SIZE
module-attribute
Size in bytes of the MRI-parameter footer (five big-endian floats).
Classes
MghParser
magic
MghParser(
image: MGHImage | None = None,
_header: MGHHeader | None = None,
_good_ras: bool | None = None,
_tags: bytes | None = None,
)
Bases: DataModelBase, FreesurferFormat, BinaryFileParserWriter
Base class for objects that are encoded by an MGH or MGZ file.
It holds the nibabel image or header (image and header, as in
NiftiParser), the raw
goodRASFlag and the trailing tags, and exposes the voxels, the voxel
coordinate system and the voxel-to-RAS matrices FreeSurfer derives
from the header.
Attributes
header
property
writable
The nibabel MGH header: the one set explicitly, or else the
header of image, or None.
tags
property
writable
tags: bytes
The raw bytes of the trailing tags (empty when there are none).
They are kept verbatim and written back after the footer, so that they survive a round trip. They are read lazily from the source file when the object was loaded from a path.
mri_params
property
The MRI acquisition parameters of the footer.
tr, te and ti are in milliseconds, flip_angle in radians
and fov in millimetres. A value of zero means "not recorded".
shape
property
shape: tuple[int, ...] | None
The shape of the volume, (x, y, z) or (x, y, z, frames).
voxel_size
property
The voxel size in millimetres, None without a header.
vox2ras
property
The (4, 4) voxel-to-scanner-RAS matrix (mri_info --vox2ras).
Equal to nibabel's header.get_vox2ras(), except when
goodRASFlag was not positive, where FreeSurfer's defaults are
used.
vox2tkr
property
The (4, 4) voxel-to-tkr (surface) RAS matrix
(mri_info --vox2ras-tkr, header.get_vox2ras_tkr()).
data
property
writable
The voxels, (x, y, z) or (x, y, z, frames), read lazily
from image and cached, unless set explicitly.
system
property
writable
system: CoordinateSystem | None
The voxel coordinate system (x, y, z[, t]), in F order,
derived from header unless set explicitly.
EXTENSIONS
class-attribute
EXTENSIONS: tuple[str, ...] = ()
File extensions handled by this parser, e.g. (".nii", ".nii.gz").
Used as a first, cheap dispatch pass. When several parsers match,
the longest matching extension wins, so a parser declaring
".nii.gz" takes precedence over one declaring ".gz".
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:
from_file
classmethod
Build the object from an MGH or MGZ file.
A local file whose name matches its content (.mgz or .mgh.gz
when gzipped, .mgh when not) is handed to nibabel by
path, through from_filename, so that the voxels are
memory-mapped and read lazily.
nibabel cannot open any other file by name: a remote one (which
has no local path), or one whose name it would take for another
codec (it picks the codec from the name). Such a file is read
into memory and handed to nibabel as a stream (see
from_fileobj): the stream nibabel reads the voxels from
lazily must outlive the file, which is closed on return.
from_fileobj
classmethod
Build the object from an open MGH or MGZ file object.
The image is read with nibabel's stream API, gzipped or not
(the compression is sniffed from the magic bytes, as a stream has
no name). As for NIfTI, the voxels are read lazily from the
stream, so the caller keeps it open for as long as they may be
read; the header, goodRASFlag and trailing tags are read right
away.
A stream that cannot seek is read into memory first: the leading
bytes must be read twice (for goodRASFlag, then by nibabel),
and its compression cannot be sniffed otherwise.
from_bytes
classmethod
Build the object from MGH bytes (or gzipped MGZ bytes).
from_nibabel
classmethod
from_nibabel(mgh: _MghObject, **kwargs) -> Self
Build the object from an already-loaded nibabel MGH header
or image.
to_nibabel
Build the nibabel image that encodes this object.
Each concrete MGH format overrides this method; the other writer methods are defined in terms of it.
to_bytes
Return the MGH encoding of the object: header, voxels, footer and
trailing tags. With compress=True, return the gzipped (MGZ)
encoding instead.
to_filename
to_filename(filename: FilenameLike, **kwargs) -> None
Write the object to a file, gzipped (MGZ) when its name ends
with .mgz or .gz, unless compress says otherwise.
to_fileobj
to_fileobj(file: IO, **kwargs) -> None
Write the MGH encoding of the object (MGZ with
compress=True) to an open file object.
sniff_fileobj
classmethod
Score how confident the class is that an open file object holds an MGH header, gzipped or not.
The content is recognised from its leading fields -- a version of 1, four positive dimensions and a known voxel type -- not from the file name.
sniff_bytes
classmethod
Score how confident the class is that bytes hold an MGH header, 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 |
sniff_file
classmethod
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 |
sniff_filename
classmethod
sniff_filename(
filename: FilenameLike,
error: bool | Type[Exception] = False,
**kwargs,
) -> float
Determine if the given filename is of the type that this parser can handle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
FilenameLike
|
The filename to sniff. |
required |
error
|
bool | type[Exception]
|
If not False, raise an error if the filename cannot be sniffed. |
False
|
**kwargs
|
Parser-specific options. |
{}
|
Returns:
| Type | Description |
|---|---|
float
|
Confidence that the filename is of this type, in |
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 |
sniff_text
classmethod
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 |
sniff_lines
classmethod
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 |
sniff_line
classmethod
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 |
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 |
from_spec
classmethod
from_spec(spec: SourceSpec, **kwargs) -> Self
Build an object from an unqualified structured source.
from_filename
classmethod
from_filename(filename: FilenameLike, **kwargs) -> Self
Build an object from a filename.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
FilenameLike
|
The filename 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
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_line
classmethod
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. |
save
save(file: FileLike, **kwargs) -> None
Write the object to a file (path or file-like object).
This is the generic front door to the to_* family. It is named
save rather than to because to already means something else
on the data models these parsers are mixed into: Transformation.to
converts an object to another type. A writer's to was shadowed
by it on every writable transformation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file
|
FileLike
|
The file to write to. |
required |
**kwargs
|
Parser-specific options. |
{}
|
to_file
to_file(file: FileLike, **kwargs) -> None
Write the object to a file (path or file-like object).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file
|
FileLike
|
The file to write to. |
required |
**kwargs
|
Parser-specific options. |
{}
|
to_text
to_text(**kwargs) -> str
Return a text version of the file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
Parser-specific options. |
{}
|
Returns:
| Type | Description |
|---|---|
str
|
A text version of the file. |
to_lines
Return a text version of the file as an iterable of lines.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
Parser-specific options. |
{}
|
Returns:
| Type | Description |
|---|---|
Iterator[str]
|
An iterable of lines representing the object. |
to_line
to_line(**kwargs) -> str
Return a line representing the object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
Parser-specific options. |
{}
|
Returns:
| Type | Description |
|---|---|
str
|
A line representing the object. |
from_dict
classmethod
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
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
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.