Skip to content

brainhops.datamodel.units

Units of measurement, backed by a private pint registry.

A Unit is built from a name -- Unit("mm"), Unit("millisecond"), Unit("s/mm^2") -- and is an interned, hashable, picklable value: two spellings of the same unit give equal units (Unit("mm") == Unit("millimeter")), and the same spelling gives the same object.

The name is parsed by pint, through a registry that belongs to brainhops and that is extended with the units imaging data needs: the index units (index, voxel, pixel, of dimension index), the arbitrary unit (a.u.) and the Hounsfield unit (HU). pint is imported, and the registry built, the first time a name is parsed, not when brainhops is imported. pint types never appear in the API, apart from the Unit.to_pint and Unit.from_pint escape hatches.

Units restricted to a dimension

A subclass of Unit can be restricted to a dimension, and then only builds units of that dimension. SpaceUnit (length), TimeUnit (time) and IndexUnit (index) are declared this way:

class SpaceUnit(Unit, dimension="length"): ...

and any other dimension can be asked for with a subscript, which builds (and caches) such a class:

DiffusionUnit = Unit["time / length ** 2"]
DiffusionUnit("s/mm^2")   # 'second / millimeter ** 2'
DiffusionUnit("mm")       # ValueError: 'millimeter' is not a ...

These classes are what a field's type hint names, so that a field typed Optional[Union[SpaceUnit, IndexUnit]] holds a unit of length, an index unit or nothing, and converts a name to one of these.

A dimension is written with pint's base dimensions (length, time, mass, ..., and brainhops' index), with or without pint's square brackets: "time / length ** 2" is "[time] / [length] ** 2".

Unit(name) returns an instance of the declared class of the unit's dimension, so isinstance(Unit("mm"), SpaceUnit) is true.

Angles

Angles are dimensionless, as pint has them: a degree is compatible with a percent. A dedicated angle dimension may be introduced later.

Classes

Unit

Unit(*args: Any, **kwargs: Any)

A unit of measurement.

Unit(name) parses a name, such as "mm", "micrometer", "µm", "ms", "Hz", "s/mm^2" or "voxel", and returns the unit it stands for: an instance of SpaceUnit, TimeUnit or IndexUnit when the unit is a length, a duration or an index, and of Unit otherwise.

Units are values: two spellings of the same unit give equal units with equal hashes, and the same unit built twice through the same class is the same object. A name that is not a unit raises a ValueError.

A subclass restricted to a dimension (see the module documentation) only builds units of that dimension, and raises a ValueError for any other.

Parameters:

Name Type Description Default
unit str | Unit

The name of the unit, or a unit.

required

Attributes

dimension class-attribute
dimension: str | None = None

The dimension that the class restricts its units to, such as "length", or None for any.

name property
name: str

The unit's name, in full, such as "millimeter" or "second / millimeter ** 2".

symbol property
symbol: str

The unit's symbol, such as "mm" or "s / mm ** 2". The micro prefix is always the Greek mu (U+03BC), as in "μm".

dimensionality property
dimensionality: str

The unit's dimension, such as "length" or "1 / time".

type property
type: str

The kind of quantity the unit measures: "space", "time" or "index", or else its dimension ("1 / time", "dimensionless", ...).

Two units with the same type can be converted into each other.

prefix property
prefix: str | None

The SI prefix of a unit such as the millimeter ("milli"), or None for a unit without one or a compound unit.

scale property
scale: float

The size of the unit in the base units of its dimension: in meters for a length, in seconds for a duration, and in indices for an index unit (1.0).

log10_scale property
log10_scale: int | float

The base-10 logarithm of the unit's scale: an int when the scale is a power of ten (the millimeter, -3), a float otherwise (the inch).

Methods:

__class_getitem__
__class_getitem__(dimension: str) -> Type[Unit]

The class of the units of a dimension, such as Unit["time / length ** 2"]. It is built once per dimension, and Unit["length"] is SpaceUnit.

from_pint classmethod
from_pint(unit: Any) -> Self

The unit of a pint unit, from any registry that names it the way brainhops' registry does.

__str__
__str__() -> str

The unit's name, such as "millimeter".

__repr__
__repr__() -> str

The unit's name, quoted.

to_pint
to_pint() -> Unit

The unit in brainhops' private pint registry.

This is an escape hatch to pint, the converse of from_pint; it is the only place where a pint object comes out of brainhops.

is_compatible_with
is_compatible_with(other: Unit | str) -> bool

Whether the unit converts into other: whether the two have the same dimension.

SpaceUnit

SpaceUnit(*args: Any, **kwargs: Any)

Bases: Unit

A unit of length, such as the millimeter.

Attributes

dimension class-attribute
dimension: str | None = None

The dimension that the class restricts its units to, such as "length", or None for any.

name property
name: str

The unit's name, in full, such as "millimeter" or "second / millimeter ** 2".

symbol property
symbol: str

The unit's symbol, such as "mm" or "s / mm ** 2". The micro prefix is always the Greek mu (U+03BC), as in "μm".

dimensionality property
dimensionality: str

The unit's dimension, such as "length" or "1 / time".

type property
type: str

The kind of quantity the unit measures: "space", "time" or "index", or else its dimension ("1 / time", "dimensionless", ...).

Two units with the same type can be converted into each other.

prefix property
prefix: str | None

The SI prefix of a unit such as the millimeter ("milli"), or None for a unit without one or a compound unit.

scale property
scale: float

The size of the unit in the base units of its dimension: in meters for a length, in seconds for a duration, and in indices for an index unit (1.0).

log10_scale property
log10_scale: int | float

The base-10 logarithm of the unit's scale: an int when the scale is a power of ten (the millimeter, -3), a float otherwise (the inch).

Methods:

__class_getitem__
__class_getitem__(dimension: str) -> Type[Unit]

The class of the units of a dimension, such as Unit["time / length ** 2"]. It is built once per dimension, and Unit["length"] is SpaceUnit.

from_pint classmethod
from_pint(unit: Any) -> Self

The unit of a pint unit, from any registry that names it the way brainhops' registry does.

__str__
__str__() -> str

The unit's name, such as "millimeter".

__repr__
__repr__() -> str

The unit's name, quoted.

to_pint
to_pint() -> Unit

The unit in brainhops' private pint registry.

This is an escape hatch to pint, the converse of from_pint; it is the only place where a pint object comes out of brainhops.

is_compatible_with
is_compatible_with(other: Unit | str) -> bool

Whether the unit converts into other: whether the two have the same dimension.

TimeUnit

TimeUnit(*args: Any, **kwargs: Any)

Bases: Unit

A unit of time, such as the second.

Attributes

dimension class-attribute
dimension: str | None = None

The dimension that the class restricts its units to, such as "length", or None for any.

name property
name: str

The unit's name, in full, such as "millimeter" or "second / millimeter ** 2".

symbol property
symbol: str

The unit's symbol, such as "mm" or "s / mm ** 2". The micro prefix is always the Greek mu (U+03BC), as in "μm".

dimensionality property
dimensionality: str

The unit's dimension, such as "length" or "1 / time".

type property
type: str

The kind of quantity the unit measures: "space", "time" or "index", or else its dimension ("1 / time", "dimensionless", ...).

Two units with the same type can be converted into each other.

prefix property
prefix: str | None

The SI prefix of a unit such as the millimeter ("milli"), or None for a unit without one or a compound unit.

scale property
scale: float

The size of the unit in the base units of its dimension: in meters for a length, in seconds for a duration, and in indices for an index unit (1.0).

log10_scale property
log10_scale: int | float

The base-10 logarithm of the unit's scale: an int when the scale is a power of ten (the millimeter, -3), a float otherwise (the inch).

Methods:

__class_getitem__
__class_getitem__(dimension: str) -> Type[Unit]

The class of the units of a dimension, such as Unit["time / length ** 2"]. It is built once per dimension, and Unit["length"] is SpaceUnit.

from_pint classmethod
from_pint(unit: Any) -> Self

The unit of a pint unit, from any registry that names it the way brainhops' registry does.

__str__
__str__() -> str

The unit's name, such as "millimeter".

__repr__
__repr__() -> str

The unit's name, quoted.

to_pint
to_pint() -> Unit

The unit in brainhops' private pint registry.

This is an escape hatch to pint, the converse of from_pint; it is the only place where a pint object comes out of brainhops.

is_compatible_with
is_compatible_with(other: Unit | str) -> bool

Whether the unit converts into other: whether the two have the same dimension.

IndexUnit

IndexUnit(*args: Any, **kwargs: Any)

Bases: Unit

An index unit: coordinates count the elements of an array rather than measure a quantity.

Its units are index, voxel and pixel; they are distinct units of the same size, so they convert into each other with a factor of one. IndexUnit() is the index.

An axis whose unit is an index unit is an array axis -- its coordinates are positions in the array, so they run 0 to N-1 over a finite number of elements, and reversing it shifts the origin by one less than its extent rather than flipping a sign about it. This is the convention OME-Zarr writes down by giving such an axis no unit at all, and the scale transformation is what converts the indices to a physical unit.

Note

This is deliberately distinct from unit=None, which means the unit is unspecified -- nothing is claimed either way, and no conversion and no origin shift follow from it. It is also distinct from a dimensionless physical unit, such as the percent, which is a real, convertible unit. An index unit never converts into a physical unit. See is_indexunit.

Attributes

dimension class-attribute
dimension: str | None = None

The dimension that the class restricts its units to, such as "length", or None for any.

name property
name: str

The unit's name, in full, such as "millimeter" or "second / millimeter ** 2".

symbol property
symbol: str

The unit's symbol, such as "mm" or "s / mm ** 2". The micro prefix is always the Greek mu (U+03BC), as in "μm".

dimensionality property
dimensionality: str

The unit's dimension, such as "length" or "1 / time".

type property
type: str

The kind of quantity the unit measures: "space", "time" or "index", or else its dimension ("1 / time", "dimensionless", ...).

Two units with the same type can be converted into each other.

prefix property
prefix: str | None

The SI prefix of a unit such as the millimeter ("milli"), or None for a unit without one or a compound unit.

scale property
scale: float

The size of the unit in the base units of its dimension: in meters for a length, in seconds for a duration, and in indices for an index unit (1.0).

log10_scale property
log10_scale: int | float

The base-10 logarithm of the unit's scale: an int when the scale is a power of ten (the millimeter, -3), a float otherwise (the inch).

Methods:

__class_getitem__
__class_getitem__(dimension: str) -> Type[Unit]

The class of the units of a dimension, such as Unit["time / length ** 2"]. It is built once per dimension, and Unit["length"] is SpaceUnit.

from_pint classmethod
from_pint(unit: Any) -> Self

The unit of a pint unit, from any registry that names it the way brainhops' registry does.

__str__
__str__() -> str

The unit's name, such as "millimeter".

__repr__
__repr__() -> str

The unit's name, quoted.

to_pint
to_pint() -> Unit

The unit in brainhops' private pint registry.

This is an escape hatch to pint, the converse of from_pint; it is the only place where a pint object comes out of brainhops.

is_compatible_with
is_compatible_with(other: Unit | str) -> bool

Whether the unit converts into other: whether the two have the same dimension.

Functions:

is_indexunit

is_indexunit(unit: Unit | Type[Unit] | None) -> bool

Whether unit is an index unit (an instance or a class), i.e. the axis is an array axis.

is_physicalunit

is_physicalunit(unit: Unit | Type[Unit] | None) -> bool

Whether unit measures a physical quantity.

True for a unit such as a millimetre, a second or a percent. False for None, which leaves the unit unspecified, for an IndexUnit, which says the coordinates count the elements of an array rather than measure anything, and for a class, which is a kind of unit rather than one -- so a conversion factor to another physical unit exists exactly when this is true of both and they have the same dimension.

is_spaceunit

is_spaceunit(unit: Unit | Type[Unit] | None) -> bool

Whether unit is a unit of space, a length (an instance or a class).

is_timeunit

is_timeunit(unit: Unit | Type[Unit] | None) -> bool

Whether unit is a unit of time (an instance or a class).