numpy-unit

Build Status Documentation Status codecov license

This package provides a tool for scientific computing by keeping track of the unit when performing classical operations on a multi-dimensionnal array with (almost) no extra-cost comparing to the standard numpy array.
The ArrayUnit class supports every operation a numpy.ndarray can handle (because it is a derived class of numpy.ndarray) but the operators are overloaded in order to perform transformations on the Unit contained in every ArrayUnit.

Install

pip install numpy-unit

Examples

>>> import numpy as np
>>> from numpy_unit import Unit, ArrayUnit
>>>
>>> m = Unit('m')
>>> sm2 = Unit('s', -2)
>>> complex_unit = Unit({'my_unit': 0.5, '€': 1, 'capita': 2}) * (sm2**0.5) / m
>>> print(complex_unit)
€·capita²·my_unit^0.5·m⁻¹·s⁻¹
>>>
>>> arr = np.linspace(1,10,10, dtype=float)
>>> a = ArrayUnit(arr, m)
>>> b = ArrayUnit(arr**2, sm2)
>>> print(a, '\\n+\\n', 1, '\\n=\\n', a + 1)
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.] m
+
1
=
[ 2.  3.  4.  5.  6.  7.  8.  9. 10. 11.] m
>>> print(a, '\\n*\\n', b, '\\n=\\n', a * b)
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.] m
*
[  1.   4.   9.  16.  25.  36.  49.  64.  81. 100.] s⁻²
=
[   1.    8.   27.   64.  125.  216.  343.  512.  729. 1000.] m·s⁻²

The following rules applied (where {op} is one of the following: [+, -, *, /, //, %]):

  • ArrayUnit {op} Object returns an ArrayUnit with the same unit as the ArrayUnit
  • Object {op} ArrayUnit returns an ArrayUnit with the same unit as the ArrayUnit
  • ArrayUnit {op} ArrayUnit returns an ArrayUnit combining the Unit of the 2 ArrayUnit or an Error
  • An Error might be raised only when two ArrayUnit are conflicting and that ArrayUnit.is_strict is set to True. Otherwise, it would print a warning.
  • An ArrayUnit is equal to a numpy.ndarray if and only if their underlying arrays are equal (np.array_equal) and the Unit of the ArrayUnit is empty.

Development

Doc of the master branch on readthedocs.io.

Features

  • [x] Basic unit system handling multiplication, division, modulo and power
  • [x] ArrayUnit wrapper for unit + ndarray
  • [x] Operators on ArrayUnit (and their variants r{op} and i{op})
    • [x] eq, ne
    • [x] add
    • [x] sub
    • [x] mul
    • [x] truediv, floordiv
    • [x] mod
    • [x] pow (but not rpow)
  • [ ] Basic ndarray function
    • [ ] mean
    • [ ] std
    • [ ] …
  • [ ] conda release

class Unit

class numpy_unit.Unit(u={}, n=1)

The Unit class that is defined by a set of (base unit, power).

It is defined by 0, 1 or many base units (str) raised to a power. For instance, an acceleration can be represented by the following dict {‘m’: 1, ‘s’: -2} (m·s⁻²).

These operators are implemented: ==, *, /, //, __pow__ as well as their __r{op}__ (except for the __pow__). However no in-place operators (__i{op}__) has been implemented yet.

Parameters:
  • u
    • If u is a string, create a Unit with a single base unit u raised to the power n (default to 1).
    • If u is a Unit, create a copy of it.
    • If u is a dict where each key is a string an each value a scalar (np.isscalar), create an Unit based on these base unit and raised to the power associated.
  • n (int, optional) – If u is a str, n is the power to which u is raised to create the new Unit. Default to 1.

Example

>>> Unit('m') == Unit('m', 1) and Unit('m') == Unit({'m': 1})
True
>>> Unit('m') * Unit('sec', -2) == Unit({'m': 1, 'sec': -2})
True
>>> Unit('€') ** 2
€²
>>> Unit('€') + Unit('$')
TypeError: unsupported operand type(s) for +: 'Unit' and 'Unit'

class ArrayUnit

class numpy_unit.ArrayUnit

The class defining a multi dimensionnal array combined with a Unit.

These operators are implemented: ==, +, -, *, /, //, %, __pow__ as well as their __r{op}__ (except for the __pow__) and their __i{op}__ variants. The level of strictness can be set in order to add, substract or use a modulo between two ArrayUnit with different Unit.

The following rules applied (where {op} is one of the following: [+, -, *, /, //, %]):

  • ArrayUnit {op} Object returns an ArrayUnit with the same unit as the ArrayUnit
  • Object {op} ArrayUnit returns an ArrayUnit with the same unit as the ArrayUnit
  • ArrayUnit {op} ArrayUnit returns an ArrayUnit combining the Unit of the 2 ArrayUnit or an Error
  • An Error might be raised only when two ArrayUnit are conflicting and that ArrayUnit.is_strict is set to True. Otherwise, it would print a warning.
  • An ArrayUnit is equal to a numpy.ndarray if and only if their underlying arrays are equal (np.array_equal) and the Unit of the ArrayUnit is empty.
Parameters:
  • input_array (numpy.ndarray) – The array on which the ArrayUnit will be based on. No copy is made, i.e. the original array and self will share the same underlying memory.
  • unit (Unit) – The Unit in which the values of the input_array are expressed.
is_set

Set the strictness to either True or False. If it is set True, a ValueError might be raised while adding, substracting or modulo two ArrayUnit with different Unit. If it is set to True, a warning is triggered when making an impossible operation.

Type:bool

Examples

>>> ArrayUnit.is_strict = True
>>> m = Unit('m')
>>> s = Unit('s', -2)
>>> arr = np.linspace(1,10,10, dtype=float)
>>> a = ArrayUnit(arr, m)
>>> b = ArrayUnit(arr**2, s)
>>> print(a, '\n+\n', 1, '\n=\n', a + 1)
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.] m
+
1
=
[ 2.  3.  4.  5.  6.  7.  8.  9. 10. 11.] m
>>> print(a, '\n-\n', arr, '\n=\n', a - arr)
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.] m
-
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]
=
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] m
>>> print(a, '\n*\n', b, '\n=\n', a * b)
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.] m
*
[  1.   4.   9.  16.  25.  36.  49.  64.  81. 100.] s⁻²
=
[   1.    8.   27.   64.  125.  216.  343.  512.  729. 1000.] m·s⁻²
>>> print(b, '\n//\n', a, '\n=\n', b / a)
[  1.   4.   9.  16.  25.  36.  49.  64.  81. 100.] s⁻²
//
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.] m
=
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.] m⁻¹·s⁻²

Indices and tables