Implements unit of measurement arithmetic, where a number is associated with a product of powers of base units and values with compatible units can be added.
The library is written in Cython for speed. The library provides the ability to statically check dimensionality type (see below) and a limited protobuffer serialization support for select units (see below). Contributions to extend support for more units are welcome.
A precompiled wheel can be installed using pip install typedunits [--pre]
.
>> import tunits
>> from tunits.units import meter, km, N, MHz
>> print(3*MHz)
Frequency(3, 'MHz')
>> print(5*meter + km)
Length(1005.0, 'm')
>> print(N/meter)
N/m
>> print((N/meter).in_base_units())
kg/s^2
>> print(2*km / tunits.Value(3, 's'))
0.666666666667 km/s
TypedUnits provides the ability to statically check the dimensionality of variables and parameters. For example mypy would complain about incompatible types for the following code.
from tunits import Frequency, LengthArray
from tunits.units import meter, km, MHz
def frequency_fn(f: Frequency) -> Frequency:
return 3*f
x = 2 * meter
x_arr = LengthArray([1, 2], km)
y = 3 * km
f = 7 * MHz
# okay
print(frequency_fn(f))
print(x + y)
print(x_arr - y)
# not okay
print(frequency_fn(x))
print(f + x)
print(x - f)
frequency_fn(x_arr)
$ mypy my_code.py
my_code.py:18: error: Argument 1 to "frequency_fn" has incompatible type "Length"; expected "Frequency" [arg-type]
my_code.py:19: error: No overload variant of "__add__" of "Value" matches argument type "Length" [operator]
my_code.py:19: note: Possible overload variants:
my_code.py:19: note: def __add__(self, int | float | complex | number[Any], /) -> Frequency
my_code.py:19: note: def __add__(self, ValueArray | list[Any] | tuple[Any] | ndarray[Any, dtype[Any]], /) -> ValueArray
my_code.py:19: note: def __add__(self, Frequency, /) -> Frequency
my_code.py:20: error: No overload variant of "__sub__" of "Value" matches argument type "Frequency" [operator]
my_code.py:20: note: Possible overload variants:
my_code.py:20: note: def __sub__(self, int | float | complex | number[Any], /) -> Length
my_code.py:20: note: def __sub__(self, list[Any] | tuple[Any] | ndarray[Any, dtype[Any]], /) -> ValueArray
my_code.py:20: note: def __sub__(self, Length, /) -> Length
my_code.py:21: error: Argument 1 to "frequency_fn" has incompatible type "LengthArray"; expected "Frequency" [arg-type]
Found 4 errors in 1 file (checked 1 source file)
TypedUnits provides protobuffer serialization support for selected units. Contributions are welcome to increase serialization coverage.
>> from tunits import Frequency
>> from tunits.units import MHz
>>
>> v = 3*MHz
>> msg = v.to_proto()
>> print(msg)
units {
unit: HERTZ
scale: MEGA
}
real_value: 3
>> Frequency.from_proto(msg)
Frequency(3.0, 'MHz')
-
To install a precompiled wheel (add
--pre
for prelease version)pip install typedunits # [--pre]
-
To locally build the latest version from the main branch
pip install git+https://github.com/quantumlib/TypedUnits
-
For a local editable copy
git clone https://github.com/quantumlib/TypedUnits cd TypedUnits pip install -e .
-
Clone the repository.
git clone https://github.com/quantumlib/TypedUnits cd TypedUnits
All future steps assume you are in the repository's directory.
-
Install dev environment dependencies.
pip install -r dev_tools/dev.env.txt
-
Install TUnits
pip install -e .
-
Test.
pytest
dev_tools/format.sh # to format
dev_tools/format.sh --check # to verify format
Note: This is not an officially supported Google product