unxt.unitsystems#

Systems of units.

A unit system is a collection of units that are used together. In a unit system there are base units and derived units. Base units are the fundamental units of the system and derived units are constructed from the base units. For example, in the SI system, the base units are the meter, kilogram, second, ampere, kelvin, mole, and candela. Derived units are constructed from these base units, for example, the newton is a derived unit of force.

unxt provides powerful tools for defining and working with unit systems. Unit systems can be statically defined (useful for many tools and development environments) or dynamically defined (useful for interactive environments and Python’s general dynamism). Unit systems can be extended, compared, and used for decomposing units on quantities. There are many more features and tools for working with unit systems in unxt.

unxt.unitsystems.unitsystem(usys, /)#

Convert a UnitSystem to a UnitSystem.

Examples

>>> from unxt.unitsystems import unitsystem
>>> usys = unitsystem("kpc", "Myr", "Msun", "radian")
>>> usys
unitsystem(kpc, Myr, solMass, rad)
>>> unitsystem(usys) is usys
True
unxt.unitsystems.unitsystem(seq: Sequence[Any], /) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Build a unit system from a sequence of units.

Examples

>>> import unxt as u
>>> u.unitsystem(())
DimensionlessUnitSystem()
>>> u.unitsystem(("kpc", "Myr", "Msun", "radian"))
unitsystem(kpc, Myr, solMass, rad)
>>> u.unitsystem(["kpc", "Myr", "Msun", "radian"])
unitsystem(kpc, Myr, solMass, rad)

A sequence’s elements are always units, so even a single-element list builds a system (a bare string, by contrast, is looked up as a named system):

>>> u.unitsystem(["km"])
LengthUnitSystem(length=Unit("km"))
unxt.unitsystems.unitsystem(_: NoneType, /) → DimensionlessUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Dimensionless unit system from None.

Examples

>>> from unxt.unitsystems import unitsystem
>>> unitsystem(None)
DimensionlessUnitSystem()
unxt.unitsystems.unitsystem(*args: Any) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Convert a set of arguments to a UnitSystem.

Examples

>>> from unxt.unitsystems import unitsystem
>>> unitsystem("kpc", "Myr", "Msun", "radian")
unitsystem(kpc, Myr, solMass, rad)

With no arguments it is the dimensionless system, agreeing with unitsystem(None) and unitsystem([]):

>>> unitsystem()
DimensionlessUnitSystem()
unxt.unitsystems.unitsystem(name: str, /) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Return unit system from name.

Examples

>>> from unxt.unitsystems import unitsystem
>>> unitsystem("galactic")
unitsystem(kpc, Myr, solMass, rad)
>>> unitsystem("solarsystem")
unitsystem(AU, yr, solMass, rad)
>>> unitsystem("dimensionless")
DimensionlessUnitSystem()
>>> unitsystem("planck")
LengthMassTimeTemperatureUnitSystem(length=Unit("l_P"), mass=Unit("m_P"), time=Unit("t_P"), temperature=Unit("T_P"))

A single string is looked up as a system name, not a unit. A string that is not a registered system – e.g. a unit like "m" – raises a clear error that names the registered systems and points to the unit path:

>>> try:
...     unitsystem("m")
... except ValueError as e:
...     print(e)
'm' is not a registered unit system (available: ...). If you meant a unit,
convert it first, e.g. unitsystem(unxt.unit('m')).
unxt.unitsystems.unitsystem(usys: AbstractUnitSystem, *args: Any) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Create a unit system from an existing unit system and additional units.

Examples

We can add a new unit definition to an existing unit system:

>>> from unxt.unitsystems import unitsystem
>>> usys = unitsystem("galactic")
>>> unitsystem(usys, "km/s")
AngleLengthMassSpeedTimeUnitSystem(angle=Unit("rad"), length=Unit("kpc"), mass=Unit("solMass"), speed=Unit("km / s"), time=Unit("Myr"))

We can also override the base unit of an existing unit system. Replacing the length still leaves a length/time/mass/angle system, so it is recognized as the built-in LTMAUnitSystem shape:

>>> new_usys = unitsystem(usys, "pc")
>>> new_usys
unitsystem(pc, Myr, solMass, rad)
unxt.unitsystems.unitsystem(flag: type[AbstractUSysFlag], *_: Any) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Raise an exception since the flag is abstract.

unxt.unitsystems.unitsystem(flag: type[StandardUSysFlag], *args: Any) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Create a standard unit system using the inputted units.

Examples

>>> from unxt import unitsystem, unitsystems
>>> unitsystem(unitsystems.StandardUSysFlag, "kpc", "Myr", "Msun")
LengthMassTimeUnitSystem(length=Unit("kpc"), mass=Unit("solMass"), time=Unit("Myr"))
unxt.unitsystems.unitsystem(flag: type[DynamicalSimUSysFlag], *args: Any, G: float | int = 1.0) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Make a dynamical unit system.

Examples

>>> from unxt.unitsystems import unitsystem, DynamicalSimUSysFlag
>>> unitsystem(DynamicalSimUSysFlag, "m", "kg")
LengthMassTimeUnitSystem(length=Unit("m"), mass=Unit("kg"), time=Unit("122404 s"))
unxt.unitsystems.unitsystem(flag: type[HEPUSysFlag], /, *args: Any, energy: Any = 'GeV') → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Make a high-energy-physics unit system: hbar = c = 1.

One free scale remains, the keyword-only energy (default 1 GeV).

Examples

>>> from unxt.unitsystems import unitsystem, HEPUSysFlag
>>> unitsystem(HEPUSysFlag)
LengthMassTimeUnitSystem(length=Unit("...e-16 m"), mass=Unit("...e-27 kg"), time=Unit("...e-25 s"))
>>> unitsystem(HEPUSysFlag, energy="TeV")["time"]
Unit("...e-28 s")
unxt.unitsystems.unitsystem(flag: type[GeometrizedUSysFlag], /, *args: Any, length: Any = 'm') → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Make a geometrized (general-relativity) unit system: c = G = 1.

One free scale remains, the keyword-only length (default 1 meter).

Examples

>>> from unxt.unitsystems import unitsystem, GeometrizedUSysFlag
>>> unitsystem(GeometrizedUSysFlag)
LengthMassTimeUnitSystem(length=Unit("m"), mass=Unit("...e+27 kg"), time=Unit("...e-09 s"))
>>> unitsystem(GeometrizedUSysFlag, length="km")["length"]
Unit("km")
unxt.unitsystems.unitsystem(flag: type[PlanckUSysFlag], /, *args: Any) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Make a Planck unit system: hbar = c = G = k_B = 1.

Fully determined – there are no free scales. The base units are the Planck length, mass, time, and temperature.

Examples

>>> from unxt.unitsystems import unitsystem, PlanckUSysFlag
>>> unitsystem(PlanckUSysFlag)
LengthMassTimeTemperatureUnitSystem(length=Unit("l_P"), mass=Unit("m_P"), time=Unit("t_P"), temperature=Unit("T_P"))
unxt.unitsystems.unitsystem(flag: type[AtomicUSysFlag], /, *args: Any) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Make an atomic (Hartree) unit system: m_e = hbar = e = 4*pi*eps0 = 1.

Fully determined – there are no free scales. The base units are the Bohr radius (length), electron mass, the atomic unit of time (hbar / E_h with E_h the Hartree energy), and the elementary charge.

Examples

>>> from unxt.unitsystems import unitsystem, AtomicUSysFlag
>>> unitsystem(AtomicUSysFlag)
LengthMassTimeElectricalChargeUnitSystem(length=Unit("a_0"), mass=Unit("m_e"), time=Unit("t_au"), electrical_charge=Unit("e"))
unxt.unitsystems.unitsystem(value: UnitSystem, /) → AbstractUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Return a gala.units.UnitSystem as a unxt.AbstractUnitSystem.

Examples

>>> import unxt as u
>>> import gala.units as gu
>>> import astropy.units as apyu
>>> usys = gu.UnitSystem(apyu.km, apyu.s, apyu.Msun, apyu.radian)
>>> u.unitsystem(usys)
unitsystem(km, s, solMass, rad)
unxt.unitsystems.unitsystem(_: DimensionlessUnitSystem, /) → DimensionlessUnitSystem
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

Return a gala.units.DimensionlessUnitSystem as a unxt.DimensionlessUnitSystem.

Examples

>>> import unxt as u
>>> from gala.units import DimensionlessUnitSystem
>>> usys = DimensionlessUnitSystem()
>>> u.unitsystem(usys)
DimensionlessUnitSystem()
Parameters:

usys (AbstractUnitSystem)

Return type:

AbstractUnitSystem

unxt.unitsystems.unitsystem_of(obj, /)#

Return the unit system of an object.

unxt.unitsystems.unitsystem_of(obj: Any, /) → DimensionlessUnitSystem
Parameters:

obj (Any)

Return type:

Any

Return the unit system of the object.

Examples

>>> from unxt.unitsystems import unitsystem_of
>>> unitsystem_of(1)
DimensionlessUnitSystem()
unxt.unitsystems.unitsystem_of(obj: AbstractUnitSystem, /) → AbstractUnitSystem
Parameters:

obj (Any)

Return type:

Any

Return the unit system from the unit system.

Examples

>>> from unxt.unitsystems import galactic, unitsystem_of
>>> unitsystem_of(galactic) is galactic
True
Parameters:

obj (Any)

Return type:

Any

class unxt.unitsystems.AbstractUnitSystem#

Bases: object

Represents a system of units.

This class behaves like a dictionary with keys set by physical types (i.e. “length”, “velocity”, “energy”, etc.). If a unit for a particular physical type is not specified on creation, a composite unit will be created with the base units. See the examples below for some demonstrations.

Examples

If only base units are specified, any physical type specified as a key to this object will be composed out of the base units:

>>> from unxt import unitsystem
>>> usys = unitsystem("m", "s", "kg", "radian")
>>> usys
unitsystem(m, s, kg, rad)
>>> usys["velocity"]
Unit("m / s")

This unit system defines energy:

>>> usys = unitsystem("m", "s", "kg", "radian", "erg")
>>> usys["energy"]
Unit("erg")

This is useful for Galactic dynamics where lengths and times are usually given in terms of kpc and Myr, but velocities are often specified in km/s:

>>> usys = unitsystem("kpc", "Myr", "Msun", "radian", "km / s")
>>> usys["velocity"]
Unit("km / s")

Unit systems can be hashed:

>>> isinstance(hash(usys), int)
True

And iterated over:

>>> [x for x in usys]
[Unit("rad"), Unit("kpc"), Unit("solMass"), Unit("km / s"), Unit("Myr")]

With length equal to the number of base units

>>> len(usys)
5
property base_dimensions: tuple[PhysicalType, ...]#

Dimensions required for the unit system.

property base_units: tuple[UnitBase | FunctionUnitBase, ...]#

List of core units.

final class unxt.unitsystems.DimensionlessUnitSystem(dimensionless: Annotated[UnitBase, PhysicalType('dimensionless')] = Unit(dimensionless))#

Bases: AbstractUnitSystem

A unit system with only dimensionless units.

Prefer the dimensionless realization from unxt.unitsystems. Distinct instances compare equal by value:

Examples

>>> from unxt.unitsystems import DimensionlessUnitSystem
>>> dims1 = DimensionlessUnitSystem()
>>> dims2 = DimensionlessUnitSystem()
>>> dims1 == dims2
True
Parameters:

dimensionless (UnitBase)

dimensionless: Annotated[UnitBase, PhysicalType('dimensionless')]#

The dimensionless unit.

property base_dimensions: tuple[PhysicalType, ...]#

Dimensions required for the unit system.

property base_units: tuple[UnitBase | FunctionUnitBase, ...]#

List of core units.

final class unxt.unitsystems.LTMAUnitSystem(length: Annotated[UnitBase, PhysicalType('length')], time: Annotated[UnitBase, PhysicalType('time')], mass: Annotated[UnitBase, PhysicalType('mass')], angle: Annotated[UnitBase, PhysicalType('angle')])#

Bases: AbstractUnitSystem

Length, time, mass, angle unit system.

Parameters:
length: Annotated[UnitBase, PhysicalType('length')]#

Units for the length dimension.

time: Annotated[UnitBase, PhysicalType('time')]#

Units for the time dimension.

mass: Annotated[UnitBase, PhysicalType('mass')]#

Units for the mass dimension.

angle: Annotated[UnitBase, PhysicalType('angle')]#

Units for the angle ‘dimension’.

property base_dimensions: tuple[PhysicalType, ...]#

Dimensions required for the unit system.

property base_units: tuple[UnitBase | FunctionUnitBase, ...]#

List of core units.

class unxt.unitsystems.AbstractUSysFlag(*_, **__)#

Bases: object

Abstract class for unit system flags to provide dispatch control.

Unit system flags are used to indicate the type of unit system being defined. They are not intended to be instantiated and are used to provide dispatch control for defining unit systems.

Raises:

ValueError – If an attempt is made to instantiate a unit system flag class.

Parameters:

See also

None

Function to define a unit system. The AbstractUSysFlag can be provided as the first argument to indicate the type of unit system being defined. This is useful for multiple-dispatching to the correct constructor.

Examples

For this example we will use the unxt.unitsystems.StandardUSysFlag, which indicates the standard construction of a unit system directly from the set of base units. Flags like unxt.unitsystems.DynamicalSimUSysFlag can be used to create a unit system where the gravitational constant G is unit-less and units are defined accordingly.

>>> import unxt

Define a unit system with the standard flag:

>>> unxt.unitsystem(unxt.unitsystems.StandardUSysFlag, "m", "kg", "s")
LengthMassTimeUnitSystem(length=Unit("m"), mass=Unit("kg"), time=Unit("s"))
class unxt.unitsystems.StandardUSysFlag(*_, **__)#

Bases: AbstractUSysFlag

Flag to indicate a standard unit system with no additional arguments.

Examples

>>> from unxt.unitsystems import unitsystem, StandardUSysFlag

Define a unit system with the standard flag:

>>> unitsystem(StandardUSysFlag, "m", "kg", "s")
LengthMassTimeUnitSystem(length=Unit("m"), mass=Unit("kg"), time=Unit("s"))

Further examples may be found in the unitsystem docs.

Parameters:
class unxt.unitsystems.DynamicalSimUSysFlag(*_, **__)#

Bases: AbstractUSysFlag

Flag to indicate a unit system with optional definition of G.

Examples

>>> from unxt.unitsystems import unitsystem, DynamicalSimUSysFlag

Define a unit system with the dynamical simulation flag:

>>> unitsystem(DynamicalSimUSysFlag, "m", "kg")
LengthMassTimeUnitSystem(length=Unit("m"), mass=Unit("kg"), time=Unit("122404 s"))

Further examples may be found in the unitsystem docs.

Parameters:
class unxt.unitsystems.NaturalUSysFlag(*_, **__)#

Bases: AbstractUSysFlag

Base flag for natural unit systems.

Natural unit systems set a chosen set of fundamental physical constants to the dimensionless value 1. In unxt this is realized numerically: the base units are chosen so that the named constants evaluate to 1.0 in the resulting system, while the full dimensional structure is preserved (mass, length, time, … remain distinct dimensions). This mirrors DynamicalSimUSysFlag, which sets Newton’s G to 1.

This class is abstract; use one of its subclasses:

  • HEPUSysFlag : high-energy-physics units (hbar = c = 1)

  • GeometrizedUSysFlag : geometrized units (c = G = 1)

  • PlanckUSysFlag : Planck units (hbar = c = G = k_B = 1)

  • AtomicUSysFlag : atomic (Hartree) units (m_e = hbar = e = 4*pi*eps0 = 1)

Parameters:
class unxt.unitsystems.HEPUSysFlag(*_, **__)#

Bases: NaturalUSysFlag

Flag for high-energy-physics (particle) natural units: hbar = c = 1.

One free scale remains – an energy, defaulting to 1 GeV. The base units are mass = E / c**2, length = hbar * c / E, time = hbar / E.

Examples

>>> from unxt.unitsystems import unitsystem, HEPUSysFlag
>>> usys = unitsystem(HEPUSysFlag)
>>> usys
LengthMassTimeUnitSystem(length=Unit("...e-16 m"), mass=Unit("...e-27 kg"), time=Unit("...e-25 s"))
>>> [str(d) for d in usys.base_dimensions]
['length', 'mass', 'time']

A different energy scale can be chosen with the energy keyword (a larger energy gives a smaller length/time and a larger mass, since hbar = c = 1):

>>> usys_tev = unitsystem(HEPUSysFlag, energy="TeV")
>>> usys_tev["time"] == usys["time"] / 1000
True
Parameters:
class unxt.unitsystems.GeometrizedUSysFlag(*_, **__)#

Bases: NaturalUSysFlag

Flag for geometrized (general-relativity) natural units: c = G = 1.

One free scale remains – a length, defaulting to 1 meter. The base units are time = length / c, mass = c**2 * length / G.

Examples

>>> from unxt.unitsystems import unitsystem, GeometrizedUSysFlag
>>> usys = unitsystem(GeometrizedUSysFlag)
>>> usys
LengthMassTimeUnitSystem(length=Unit("m"), mass=Unit("...e+27 kg"), time=Unit("...e-09 s"))
>>> [str(d) for d in usys.base_dimensions]
['length', 'mass', 'time']

A different length scale can be chosen with the length keyword:

>>> unitsystem(GeometrizedUSysFlag, length="km")["length"]
Unit("km")
Parameters:
class unxt.unitsystems.PlanckUSysFlag(*_, **__)#

Bases: NaturalUSysFlag

Flag for Planck natural units: hbar = c = G = k_B = 1.

Fully determined – there are no free scales. The base units are the Planck length, mass, time, and temperature.

Examples

>>> from unxt.unitsystems import unitsystem, PlanckUSysFlag
>>> usys = unitsystem(PlanckUSysFlag)
>>> usys
LengthMassTimeTemperatureUnitSystem(length=Unit("l_P"), mass=Unit("m_P"), time=Unit("t_P"), temperature=Unit("T_P"))
>>> [str(d) for d in usys.base_dimensions]
['length', 'mass', 'time', 'temperature']
Parameters:
class unxt.unitsystems.AtomicUSysFlag(*_, **__)#

Bases: NaturalUSysFlag

Flag for atomic (Hartree) natural units: m_e = hbar = e = 4*pi*eps0 = 1.

Fully determined – there are no free scales. The base units are the Bohr radius (length), electron mass, the atomic unit of time (hbar / E_h with E_h the Hartree energy), and the elementary charge.

Examples

>>> from unxt.unitsystems import unitsystem, AtomicUSysFlag
>>> usys = unitsystem(AtomicUSysFlag)
>>> usys
LengthMassTimeElectricalChargeUnitSystem(length=Unit("a_0"), mass=Unit("m_e"), time=Unit("t_au"), electrical_charge=Unit("e"))
>>> [str(d) for d in usys.base_dimensions]
['length', 'mass', 'time', 'electrical charge']
Parameters:
unxt.unitsystems.equivalent(a, b, /)#

Whether two unit systems describe the same physical structure.

Two unit systems are equivalent when they share the same set of base dimensions and, for each dimension, their units are interconvertible. Unlike ==, the specific units need not be identical – only convertible – so systems that measure the same dimensions in different (but compatible) units are equivalent.

Examples

>>> from unxt.unitsystems import galactic, solarsystem, si, equivalent

galactic (kpc, Myr, solMass, rad) and solarsystem (AU, yr, solMass, rad) have the same base dimensions and interconvertible units:

>>> equivalent(galactic, solarsystem)
True
>>> equivalent(galactic, galactic)
True

A system with different base dimensions is not equivalent:

>>> equivalent(galactic, si)
False
unxt.unitsystems.equivalent(a: AbstractQuantity, b: AbstractQuantity, /) → Any
Parameters:
Return type:

bool

Whether two quantities are physically equal, accounting for units.

This is the unit-aware counterpart to == (which is unit-blind for StaticValue-backed quantities – see AbstractQuantity.__eq__). The result mirrors ==’s shape: a scalar bool for StaticValue-backed operands, and an element-wise dimensionless Quantity of booleans for array-backed ones. Quantities with incompatible dimensions are never equivalent (and this never raises).

Examples

>>> import numpy as np
>>> import unxt as u
>>> from unxt.quantity import StaticValue

Physically-equal static quantities in different units are equivalent, even though unit-blind == reports False:

>>> a = u.Q(StaticValue(np.array([1.0, 2.0])), "m")
>>> b = u.Q(StaticValue(np.array([0.001, 0.002])), "km")
>>> a == b
False
>>> u.equivalent(a, b)
True
>>> a.is_equivalent(b)
True

Array-backed quantities compare element-wise (unit-aware):

>>> u.equivalent(u.Q([1.0, 2.0], "m"), u.Q([0.001, 0.009], "km"))
Quantity(Array([ True, False], dtype=bool), unit='')

Incompatible dimensions are never equivalent:

>>> u.equivalent(u.Q(1.0, "m"), u.Q(1.0, "s"))
False
Parameters:
Return type:

bool