Units 1: Basics#
Overview#
This section explains how to use the pyxx.units module to define
units, and perform unit conversions and related operations.
Note
If you’re already familiar with the basics of units and unit conversions in the PyXX package and just need to use the unit converters, head over to the Units 2: Unit Converters page.
Setup#
To follow along with these examples, begin by opening a Python terminal and importing the PyXX package:
>>> import pyxx
Creating Units#
Basics#
As discussed in the Unit Conversion Concepts section, to define a unit, we need to specify several pieces of information: (1) the system of units to which the unit belongs, (2) the powers to which the base units are raised to relate the unit to the base units, (3) a function to convert quantities from the given unit to base units, and (4) an inverse function to convert quantities from the base units to the given unit.
There are several ways to define units that meet such requirements. One
approach is to create pyxx.units.Unit objects. For instance, let’s
define a unit of meters. Since meters are one of the base units in the SI
system of units, this is fairly straightforward:
>>> m = pyxx.units.Unit(
... unit_system=pyxx.units.UnitSystemSI(),
... base_unit_exps=[1, 0, 0, 0, 0, 0, 0],
... to_base_function=lambda x, exp: x,
... from_base_function=lambda x, exp: x,
... identifier='m', name='meter'
... )
>>> print(m)
m - meter - [1. 0. 0. 0. 0. 0. 0.]
However, there’s an arguably easier shortcut. Suppose we want to define another
unit in the SI system of units: the millimeter. Since this unit has a linear
relationship to the base units (meters), we can define it using a
pyxx.units.UnitLinearSI. In this case, the object definition is
easier, since we don’t need to worry about the to_base_function and
from_base_function arguments – these are automatically generated for us.
Since a millimeter is \(1/1000\) of a meter, the unit can be defined as:
>>> mm = pyxx.units.UnitLinearSI(
... base_unit_exps=[1, 0, 0, 0, 0, 0, 0],
... scale=0.001, offset=0,
... identifier='mm', name='millimeter'
... )
>>> print(mm)
mm - millimeter - [1. 0. 0. 0. 0. 0. 0.] - scale: 0.001 - offset: 0.0
Unit Arithmetic#
Once we have already defined several units, we may want to create new units based on the units we have already defined. For instance, we already created a unit of meters, and suppose we also define a unit representing seconds:
>>> s = pyxx.units.UnitLinearSI(
... base_unit_exps=[0, 1, 0, 0, 0, 0, 0],
... scale=1, offset=0,
... identifier='s', name='second'
... )
>>> print(s)
s - second - [0. 1. 0. 0. 0. 0. 0.] - scale: 1.0 - offset: 0.0
Now suppose we want to define a new unit: meters per second squared. We could create an entirely new unit, like this:
>>> print(pyxx.units.UnitLinearSI(
... base_unit_exps=[1, -2, 0, 0, 0, 0, 0],
... scale=1, offset=0,
... identifier='m/s^2'
... ))
m/s^2 - [ 1. -2. 0. 0. 0. 0. 0.] - scale: 1.0 - offset: 0.0
However, there’s a much simpler, less error-prone way. We can use our existing
units m and s to create a new unit:
>>> m_s2 = m/s**2
>>> print(m_s2)
m/(s^2.0) - meter/(second^2.0) - [ 1. -2. 0. 0. 0. 0. 0.]
Supported operations include multiplication (*), division (/), and
exponents (**).
[Advanced] Unit Arithmetic with Constants
By default, multiplying or dividing a PyXX unit by a constant will result in an error being thrown. For instance, this code would result in an error:
>>> 1000 * mm # throws an error
However, there are cases in which this functionality could be useful. For instance, if we have already defined a unit of millimeters, we may want to define another unit, such as centimeters, that is a known multiple of millimeters. Fortunately, PyXX provides a means to do so.
As explained in the pyxx.units.ConstantUnitMathConventions
documentation, the meaning of multiplying a unit by a constant is ambiguous.
Thus, we must first enable this feature by selecting an appropriate math
convention; for instance, by using:
>>> from pyxx.units import Unit, ConstantUnitMathConventions
>>> Unit.CONSTANT_MATH_CONVENTION = ConstantUnitMathConventions.UNIT_BASED
Then, we can perform operations multiplying or dividing units by a constant:
>>> cm = 10 * mm
>>> print( cm.to_base(100) )
1.0
However, this is an advanced feature, and it requires detailed
understanding of the meaning of each of the options specified in
pyxx.units.ConstantUnitMathConventions. In most cases,
it is safer to leave this feature in its default setting (DISABLE):
>>> Unit.CONSTANT_MATH_CONVENTION = ConstantUnitMathConventions.DISABLE
Unit Conversions#
Checking for Ability to Convert Units#
Prior to performing a unit conversion, it can be useful to know whether two
units are “compatible” and quantities can be converted between the units.
The pyxx.units.Unit.is_convertible() method provides this
functionality.
Since the m and mm units we defined previously both belong to the same
system of units (SI) and have the same base_unit_exps property, it should
be possible to convert between these units, which we can verify using:
>>> mm.is_convertible(m)
True
>>> m.is_convertible(mm)
True
Converting To/From Base Units#
The first, and relatively simple, unit conversion we may want to perform is to convert a given quantity from a given unit to the base units, or vice versa.
For instance, to convert a value from millimeters to the base units (meters), we could run:
>>> print( mm.to_base(100) )
0.1
We can also perform conversions in cases where units are raised to an exponent. For instance, this is one way to convert \(1\ m^2\) to square millimeters:
>>> print( mm.from_base(1, exponent=2) )
1000000.0
Converting Between Units#
Perhaps a more interesting case, however, is to convert between units. This
can be accomplished using the pyxx.units.Unit.convert() method.
For instance, we previously defined units of \(m\) and \(mm\), so to convert \(2\ m\) to \(mm\), we can use:
>>> print( m.convert(2, 'to', mm) )
2000.0
We can just as easily convert “the other direction,” from \(mm\) to \(m\):
>>> print( m.convert(2, 'from', mm) )
0.002
It’s also possible to convert multiple values at once by providing a list, tuple, or NumPy array as an input:
>>> print( m.convert([1, 2, 3, 4], 'to', mm) )
[1000. 2000. 3000. 4000.]
More complex unit conversions can be performed using unit arithmetic:
>>> print( (m/s).convert([3.14, 6.28], 'to', mm/s) )
[3140. 6280.]
An even more most streamlined way to perform unit conversions is using the
pyxx.units.UnitConverter class or the unit converter CLI. Refer
to the Units 2: Unit Converters page for more detail.