Core classes of natu
As shown in the diagram below, there are two types of units (Unit): scalar units (ScalarUnit) and lambda units (LambdaUnit). Scalar units are quantities, but lambda units are not. Lambda units are essentially invertible functions that map between numbers and quantities (Quantity). All units and quantities are dimensioned objects (DimObject), meaning that their physical dimension is recorded (even if dimensionless).
Numbers, scalar units, and quantities can be used together in mathematical expressions as long as the expression is dimensionally consistent. Numbers (float, int, Fraction, etc.) are considered dimensionless.
Lambda units can only be used with numbers and quantities in certain ways. A lambda unit can be applied to generate a quantity for use in the rest of a mathematical expression. The multiplication operator (*) is overloaded so that a number times a lambda unit calls the unit’s method to map the number to a quantity. Likewise, the division operator (/) uses a lambda unit to map a quantity to a number.
The tables below summarize the type of result given by simple mathematical operations among numbers (N), scalar units (S), lambda units (L), and quantities (Q). The product or quotient of a number and a quantity or scalar unit is a quantity. This is the case even if the number is zero. For example, the product of zero and a unit still carries the dimension of the unit. In a Boolean expression, a quantity is cast as False if its value is zero. However, it is only equal to zero if its value is zero and it is dimensionless. The display unit of the first term in addition or subtraction takes precedence. If the first term is a number and the second term is a dimensionless quantity, then the result is a number.
Results of multiplication and division:
1st argument | 2nd argument | |||
---|---|---|---|---|
N | Q | S | L | |
N | N | Q | Q | Q |
Q | Q | Q [1] | Q [1] | N |
S | Q | Q [1] | S [1] | – |
L | – | – | – | – |
Results of addition and subtraction:
1st argument | 2nd argument | |||
---|---|---|---|---|
N | Q | S | L | |
N | N | N [2] | N [2] | – |
Q | Q [2] | Q | Q | – |
S | Q [2] | Q | Q | – |
L | – | – | – | – |
Key:
[1] | (1, 2, 3, 4) If the result is dimensionless, then it is returned as a number instead. |
[2] | (1, 2, 3, 4) The quantity must be dimensionless. |
Here are some consequences of this design:
Classes in this module:
Warning
Be careful if you use this package to produce conversion factors. The factor may be the reciprocal of what you first think. By the phrase “convert from x to y” (where x and y are units), we mean “convert from an expression of the quantity in x to an expression of the quantity in y.” “Quantity in unit” is typically equivalent to “quantity divided by unit”, and to get from Q/x (where Q is a quantity) to Q/y, we must multiply by x/y. For example, the conversion factor from feet to metres is ft/m (0.3048) using natu.units.
Note
Known issues:
Bases: object
Base class that records physical dimension and display unit (aka “dimensioned object”)
Initialization parameters:
dimension: Physical dimension
display_unit: Display unit
This can be an Exponents instance, a UnitExponents instance, a dict of similar form, or a string accepted by the fromstr() constructor.
Here, the physical dimension and the display unit are not checked for consistency.
dimension and dimensionless are read-only attributes (see below), but display_unit can be set using the same format as the display_unit argument above.
True if the instance is dimensionless
Initialize by directly setting the physical dimension and display unit.
Parameters:
Bases: natu.core.DimObject
Class to represent a physical quantity
Initialization parameters:
value: Value of the quantity (a numbers.Number instance)
This be expressed as the product of a number and the value of a unit. It is independent of the unit since the number scales inversely to the unit.
dimension: Physical dimension
display_unit: Display unit
This can be an Exponents instance, a UnitExponents instance, a dict of similar form, or a string accepted by the fromstr() constructor.
Examples:
Instantiation and simple operations:
>>> import natu.units
>>> mass = Quantity(1, 'M', 'kg')
>>> velocity = Quantity(1, 'L/T', 'm/s')
>>> energy = mass*velocity**2
>>> print(energy.dimension)
L2*M/T2
>>> print(energy.display_unit)
kg*m2/s2
However, it is easier to create a quantity as the product of a number and unit(s); see natu.units.
Changing the display unit:
>>> mass.display_unit = 'lb'
>>> print(mass)
2.20462... lb
Note that the value has not changed:
>>> mass
Quantity(1, 'M', 'lb') (2.20462... lb)
Although the display_unit property can be changed, quantities are otherwise immutable. The in-place operators create new instances:
>>> initial_id = id(velocity)
>>> velocity *= 0.5
>>> id(velocity) == initial_id
False
The dimension and display_unit properties of the first term are propagated to the result.
Return the length of the value if it is defined.
Initialize by directly setting the value, physical dimension, and display unit.
value: Value of the quantity (a numbers.Number instance)
This be expressed as the product of a number and the value of a unit. It is independent of the unit since the number scales inversely to the unit.
dimension: Physical dimension as an Exponents instance
display_unit: Display unit as a UnitExponents instance
Bases: natu.core.DimObject
Base class for a unit
In-place operations are blocked because the value of a unit is predefined and should not be changed.
Initialization parameters:
dimension: Physical dimension
display_unit: Display unit
This can be an Exponents instance, a UnitExponents instance, a dict of similar form, or a string accepted by the fromstr() constructor.
prefixable: True if the unit can be prefixed
dimension, dimensionless, and prefixable are read-only attributes, but display_unit can be set using the same format as the display_unit argument above.
True if the unit can be prefixed
Example:
>>> from natu.units import m, ft
>>> m.prefixable
True
>>> ft.prefixable
False
Bases: natu.core.Quantity, natu.core.Unit
Unit that involves just a scaling factor
Initialization parameters:
value: Value of the unit (a numbers.Number instance)
dimension: Physical dimension
display_unit: Display unit
This can be an Exponents instance, a UnitExponents instance, a dict of similar form, or a string accepted by the fromstr() constructor.
prefixable: True if the unit can be prefixed
Examples:
>>> from natu.units import kg, m, s
>>> # F
>>> kg
ScalarUnit(1, 'M', 'kg', False) (kg)
>>> kg*m**2/s**2
ScalarUnit(1, 'L2*M/T2', 'J', False) (J)
Note that the display unit can be changed:
>>> m.display_unit = 'ft'
>>> m
ScalarUnit(1, 'L', 'ft', True) (3.2808... ft)
Now any quantity generated from the metre (m) will display in feet (ft) instead. However, the value is unchanged; the metre still represents the same length.
Raise an error upon indexing.
Convert a quantity (instance of Quantity) to a scalar unit.
The value and dimension are taken from quantity. The display unit must be provided (via display_unit).
Example:
>>> from natu.units import ns
>>> shake = ScalarUnit.from_quantity(10*ns, 'shake')
Bases: natu.core.Unit
Unit that involves a offset or other operations besides scaling
Initialization parameters:
toquantity: Function that maps a number to a quantity
tonumber: Function that maps a quantity to a number
dimension: Physical dimension
display_unit: Display unit
This can be an Exponents instance, a UnitExponents instance, a dict of similar form, or a string accepted by the fromstr() constructor.
prefixable: True if the unit can be prefixed
Examples:
>>> from natu.units import degC, K
>>> degC
LambdaUnit(...)
>>> 25*degC/K
298.15
Bases: dict
Dictionary of units with dynamic prefixing (upon access)
Properties:
coherent_relations - List of coherent relations among the units
Each entry is an UnitExponents instance that evaluates to unity.
Generate a compound, coherent unit from existing units.
Call signature (where units is a :class:`Units` instance):
units(unit1=exp1, unit2=exp2, ...): Returns the product of unit1 raised to the power exp1, unit2 raised to the power exp2, etc.
If there are no arguments, then unity (1.0) is returned.
Example:
>>> from natu.units import _units
>>> _units(lbf=1, inch=-2)
ScalarUnit lbf/inch2 with dimension M/(L*T2) (not prefixable)
Access a simple (not compound) unit by symbol (a string).
Prefixes are supported.
Example:
>>> from natu.units import _units
>>> _units['psi']
ScalarUnit(6894.76, 'M/(L*T2)', 'psi', False) (psi)
Add units to the unit dictionary from a *.ini file or list of files (files).
Examples:
>>> from natu.core import Units
>>> from natu.config import definitions
>>> units = Units()
>>> units.load_ini([definitions[0]])
>>> units.keys()
['R', 'R_K', 'R_inf', 'c', 'k_Aprime', 'k_F', 'k_J', 'rational']
Simplify a compound unit.
This function seeks to minimize the sum of the absolute values of the exponents of the base factors by substituting coherently related units. It uses the internal coherent_relations list which is generated while parsing the *.ini files (in load_ini()). It will not always find the simplest representation because some simplifications involve first making the representation more complex.
Parameters:
unit: Unit to be simplified
This can be an UnitExponents instance or a dict of similar form.
level: Number of levels of recursion to perform
This is the number of non-minimizing substitutions that can be made while seeking the simplest representation of the unit. The default is
Returns: The new representation of the unit as an instance of the same class as the original representation (unit).
Example:
>>> # High-level/indirect:
>>> from natu.units import *
>>> print(kg*m**2/s**2)
J
>>> # Low-level/direct:
>>> from natu.units import _units
>>> print(_units.simplify('kg*m2/s2'))
J
Bases: module
Class that wraps a Units dictionary as a module
Initialization parameters:
module: The module into which the units should be wrapped
This must have the attributes __name__ and __doc__.
definitions: A *.ini file, list of files, or dictionary with units that should be inserted into the module
It is not necessary to provide prefixed versions of the units unless they should be available via wildcard import (e.g., from units_module import *).
Only one UnitsModule can be instantiated directly from *.ini files per Python session. This prevents conflicts that could arise if the units were reloaded with different base constants.
Bases: natu.exponents.Exponents
Dictionary that contains the base units of a display unit as keys and exponents of those units as values
This is natu.exponents.Exponents, except that special replacements (see unit_replacements in mod:~natu.config) are made in certain formatted strings.
Example:
>>> unit = UnitExponents('angstrom/s')*2
>>> dict(unit)
{'angstrom': 2, 's': -2}
>>> unit
angstrom2/s2
>>> print(format(unit, 'U'))
Ų s⁻²