Normalizing electronics engineering value notations using Python

In electronics engineering there is a wide variety of notations for values that need to be recognized by intuitive user interfaces. Examples include:

  • 1fA
  • 0.1A
  • 0.00001
  • 1e-6
  • 4,5nA
  • 4,500.123 A
  • 4A5
  • 4k0 A

The wide variety of options, including thousands separators, comma-as-decimal-separator and suffix-as-decimal-separator, optional whitespace and scientific notations makes it difficult to normalize values without using specialized libraries.

The script listed in this post provies a public domain yet comprehensive library to normalize such values into. For correct operation, a list of SI suffices and a list of valid units are required. Those might need to be modified for different applications.

I wrote the UliEngineering library, an Python3-only electronics library that includes parsing this notation amongst a lot of other useful functionality such as resistor selection.

A usage example is included at the bottom of the script. All functions return None if a value can’t be interpreted.

First, you need to install UliEngineering

sudo pip3 install git+https://github.com/ulikoehler/UliEngineering.git

then, you can use the functions from EngineerIO.py to parse and generate the format listed above. Besides the notations listed above, a lot of different values can be parsed.

Use normalize_engineer_notation() to get a (value, unit) tuple.

>>> from UliEngineering.EngineerIO import *
>>> normalize_engineer_notation("1 fA")
(1e-15, 'A')
>>> normalize_engineer_notation("4,500.123 A")
(4500.123, 'A')

Note that UliEngineering has a built-in list of units that needs to include your unit so it can be validated correctly.  Special unit combinations like V/√Hz or unicode prefixes like µV are also recognized.

You can also use format_value() to generate a human-readable string with SI prefix from a value and a unit:

>>> from UliEngineering.EngineerIO import *
>>> normalize_engineer_notation("4,500.123 A")
(4500.123, 'A')
>>> format_value(4.5e-6, "A")
'4.50 µA'
>>> format_value(4.5e-6, "V/√Hz")
'4.50 µV/√Hz'

If you need a customized set of units, prefices etc, you can initialize your own instance of the EngineerIO() class.

For the common case in which you only need the numeric value and don’t care about the unit, you can use normalize_numeric():

>>> from UliEngineering.EngineerIO import *
>>> normalize_numeric("4,500.123 A")
4500.123

Keep in mind that UliEngineering only works on Python3.x, as Python2 will only be supported until 2020.