jmath v4: Units for Maths & Physics

Published 2021/11/08 1039 by Jordan Hay

jmath v4.0.0 has been released! A major new feature has been introduced, one I've been quite keen to develop for a while.

v4 introduces the Unit object in jmath.units as well as some associated features. Let's see a snippet of how it behaves

# Imports
from jmath import Unit, Uncertainty
from jmath.units import define_alias

# Define Units
volt = Unit("V") # voltage
ohm = Unit("Ω") # Resistance
ampere = Unit("A") # Current

# Define an alias
# Voltage = Resistance * Current
define_alias(ohm * ampere, volt)

# Using Units
voltage_drop = Uncertainty(3, 0.2) * volt
current = Uncertainty(0.1, 0.02) * ampere
resistance = voltage_drop/current # Per Ohm's Law

>>> print(resistance)
(30 ± 8) [Ω]

Units can be defined, attach themselves to values with the '*' operator, and then resulting values are computed with operations behaving much like normal numbers. They are compatible with Python's int and float types, as well as jmath's Uncertainty.

In addition it is possible to define "aliases" for specific units with the define_alias function provided in jmath.units. An alias will override a given unit or set of units if they are produced, for SI where voltage (V) can be derived from resistance* (Ω) and current (A) as well as vice versa this proves natural.

Another useful function-define_conversion-is also provided in jmath.units. define_conversion takes two units as parameters and then either a function or a multiplier that is used to convert between the two units. Both are demonstrated in the snippet below

# MULTIPLIER METHOD
    
# Imports
from jmath import Unit
from jmath.units import define_conversion

# Define Units
kg = Unit("kg") # Mass
j = Unit("J") # Energy

# Define conversion
# Note that conversions with factors are considered invertible
define_conversion(kg, j, (3e8)**2)

mass = 3 * kg
rest_energy = mass.convert_to(j)

>>> print(rest_energy)
2.7e+17 [J]
# LAMBDA METHOD
    
# Imports
from jmath import Unit
from jmath.units import define_conversion

# Define Units
C = Unit("°C")
F = Unit("°F")

# Define conversion
# Note that with conversion functions we must define it both ways
define_conversion(C, F, lambda t: (t * 9/5) + 32)
define_conversion(F, C, lambda t: (t - 32) * 5/9)

temp_F = 35 * F
temp_C = temp_F.convert_to(C)

>>> print(temp_C)
1.6666666666666667 [°C]

Since defining heaps of units and their conversions could be quite tiresome, the SI base units and some common derived SI units are provided in jmath.units.si, and some more common units (such as the electron volt) are defined in jmath.units.other.

In addition to the brand new unit object I have also done some tidying up of other issues I found while building the unit object. Primarily these are

  • Fixing the display method for the Uncertainty object, I found this to have many issues I had never seen before while getting it working with the Unit object. These issues should be resolved now.
  • Fixing the documentation for the experimental graphics subpackage, it was totally missing and I'm not entirely sure why but it seems to be fixed now.
  • Better type hinting in the documentation, and general documentation cleanup.

Future plans for jmath include

  • New functions based on those in Python's math library that are compatible with jmath objects.
  • Upgrades to the Unit class, especially for systems of units, and perhaps a better alias/conversion system.

A final reminder that the documentation for jmath can be found at https://jmath.jordanhay.com/ and that the source code is avaliable at https://github.com/JHay0112/jmath/.

*Note that voltage (V) and resistance (Ω) are themselves also derived from base units and these conversions could also be added into a jmath unit system if it was so desired.


Source code MIT License © 2021 Jordan Hay | Website Content © 2017-2021 Jordan Hay