How to define a unit system#
unxt ships realizations for SI, CGS, galactic, solar-system and the natural unit systems, and unxt.unitsystem() will build one on the fly from any set of units. You only need a hand-written subclass when you want a named, statically defined system — one you can annotate against, dispatch on, or ship from your own package.
If you just need a system for a set of units, call unitsystem instead:
>>> import unxt as u
>>> u.unitsystem("m", "s")
LengthTimeUnitSystem(length=Unit("m"), time=Unit("s"))
Write the subclass#
Declare one Annotated field per base dimension, pairing the unit type with the dimension it measures. The class must be a frozen dataclass and must be registered as a static JAX pytree node, exactly as the built-in systems are:
>>> from dataclasses import dataclass
>>> from typing import Annotated
>>> import jax.tree_util as jtu
>>> from astropy.units import UnitBase, get_physical_type
>>> from unxt.unitsystems import AbstractUnitSystem
>>> @jtu.register_static
... @dataclass(frozen=True, slots=True)
... class MyUSys(AbstractUnitSystem):
... energy: Annotated[UnitBase, get_physical_type("energy")]
... frequency: Annotated[UnitBase, get_physical_type("frequency")]
Construct it#
A hand-built subclass stores its fields as given, so pass unit objects. String parsing is a service of the unitsystem factory, not of the dataclass.
>>> usys = MyUSys(u.unit("erg"), u.unit("Hz"))
>>> usys["energy"]
Unit("erg")
Indexing works the same as for any built-in system, including derived dimensions composed from the base units.
See also#
Unit systems — the built-in realizations and the full
unitsysteminput list.About unxt’s API conventions — why
unxtpairs a functional and an object-oriented API.