A Python library for computing with physical quantities

Magnitude implements efficient computation with physical quantities. It allows you to do mathematical operations with them as if they were numbers, taking care of the units behind the scenes.

A physical quantity is a number with a unit, like 10 km/h. Units are specified as strings. They can be any of the SI units, plus a bunch of non-SI, bits, dollars, and any combination of them. They can include the standard SI prefixes. Magnitude can operate with physical quantities, parse their units, and print them. You don’t have to worry about unit consistency or conversions; everything is handled transparently.

By default output is done either in the unit with which the Magnitude object has been created, or in basic SI units, but you can specify any output unit, as long as it can be reduced to the basic units of the physical quantity.

xkcd kB

All standard prefixes are understood, from yocto to yotta and from kibi to exbi.


It is hosted at Github. Either clone it with git:

  git clone git://

or download the package.


In the magnitude directory,

  sudo python install


  >>> from magnitude import mg
  >>> print mg(10, 'm/s') ** 2
  100.0000 m2 / s2
  >>> print (mg(10, 'm') * 2 / (10, 'm/s2')).sqrt()
  1.4142 s
  >>> tsq = mg(10, 'm') * 2 / (10, 'm/s2')
  >>> print tsq ** 0.5
  1.4142 s
  >>> print mg(1, "lightyear") / mg(1, "c")
  >>> 31557600.0000 s
  >>> y = mg(1, "lightyear") / (1, "c")
  >>> print y.ounit("year")
  1.0000 year
  >>> print y.ounit('day')
  >>> print yd
  365.2500 day
  >>> power = mg(100, 'kg') * (2, 'gravity') * (5, 'km/h')
  >>> print power
  2724.0694 m2 kg / s3
  >>> print power.ounit('mW')
  2724069.4444 mW
  >>> print power.ounit('kW')
  2.7241 kW


Available units

The basic units understood by the magnitude module are:

indicator meaning
$ dollar (’dollar’ is also acceptable)
A ampere
b bit
cd candela
K degrees Kelvin
kg kilograms
m meters
mol amount of substance
s seconds

From these basic units you can derive many other units. The magnitude package predefines these derived units:

      # Magnitudes for the base SI units
      new_mag('m', Magnitude(1.0, m=1))
      new_mag('s', Magnitude(1.0, s=1))
      new_mag('K', Magnitude(1.0, K=1))
      new_mag('kg', Magnitude(1.0, kg=1))
      new_mag('A', Magnitude(1.0, A=1))
      new_mag('mol', Magnitude(1.0, mol=1))
      new_mag('cd', Magnitude(1.0, cd=1))
      new_mag('$', Magnitude(1.0, dollar=1))
      new_mag('dollar', Magnitude(1.0, dollar=1))
      new_mag('b', Magnitude(1.0, b=1))           # bit

      # Magnitudes for derived SI units
      new_mag('B', Magnitude(8.0, b=1))
      new_mag('rad', Magnitude(1.0))  # radian
      new_mag('sr', Magnitude(1.0))  # steradian
      new_mag('Hz', Magnitude(1.0, s=-1))  # hertz
      new_mag('g', Magnitude(1e-3, kg=1))  # gram
      new_mag('N', Magnitude(1.0, m=1, kg=1, s=-2))  # newton
      new_mag('Pa', Magnitude(1.0, m=-1, kg=1, s=-2))  # pascal
      new_mag('J', Magnitude(1.0, m=2, kg=1, s=-2))  # joule
      new_mag('W', Magnitude(1.0, m=2, kg=1, s=-3))  # watt
      new_mag('C', Magnitude(1.0, s=1, A=1))  # coulomb
      new_mag('V', Magnitude(1.0, m=2, kg=1, s=-3, A=-1))  # volt
      new_mag('F', Magnitude(1.0, m=-2, kg=-1, s=4, A=2))  # farad, C/V
      new_mag('ohm', Magnitude(1.0, m=2, kg=1, s=-3, A=-2))  # ohm, V/A
      new_mag('S', Magnitude(1.0, m=-2, kg=-1, s=3, A=2))  # siemens, A/V, el cond
      new_mag('Wb', Magnitude(1.0, m=2, kg=1, s=-2, A=-1))  # weber, V.s, mag flux
      new_mag('T', Magnitude(1.0, kg=1, s=-2, A=-1))  # tesla, Wb/m2, mg flux dens
      new_mag('H', Magnitude(1.0, m=2, kg=1, s=-2, A=-2))  # henry, Wb/A, induct.
      new_mag('degC', Magnitude(1.0, K=1))  # celsius, !!
      new_mag('lm', Magnitude(1.0, cd=1))  # lumen, (=cd)), luminous flux
      new_mag('lux', Magnitude(1.0, m=-2, cd=1))  # lux, lm/m2, illuminance
      new_mag('Bq', Magnitude(1.0, s=-1))  # becquerel, activity of a radionulide
      new_mag('Gy', Magnitude(1.0, m=2, s=-2))  # gray, J/kg, absorbed dose
      new_mag('Sv', Magnitude(1.0, m=2, s=-2))  # sievert, J/kg, dose equivalent
      new_mag('kat', Magnitude(1.0, s=-1, mol=1))  # katal, catalitic activity
      # Non-SI but almost:
      new_mag('b', Magnitude(8.0, b=1))  # byte, note that B is Bel, as in dB

      ### Other
      # length
      new_mag("'", Magnitude(0.3048, m=1))  # feet
      new_mag('ft', Magnitude(0.3048, m=1))  # feet
      new_mag('inch', Magnitude(0.0254, m=1))  # inch
      new_mag('"', Magnitude(0.0254, m=1))  # inch
      new_mag('lightyear', Magnitude(2.99792458e8 * 365.25 * 86400, m=1))

      # volume
      new_mag('l', Magnitude(0.001, m=3))

      # time
      # year is tropical year, "the mean interval between vernal
      # equinoxes.  Differs from the sidereal year by 1 part in 26000
      # due to precession of the earth about its rotational axis
      # combined with precession of the perihelion of the earth's orbit"
      # (from units.dat).
      new_mag('year', Magnitude(31556925.974678401, s=1))
      new_mag('day', Magnitude(86400, s=1))
      new_mag('h', Magnitude(3600, s=1))
      new_mag('min', Magnitude(60, s=1))

      # Resolution
      new_mag('dpi', Magnitude(1.0 / 0.0254, m=-1))
      new_mag('lpi', Magnitude(1.0 / 0.0254, m=-1))

      # Velocity
      new_mag('ips', Magnitude(0.0254, m=1, s=-1))
      new_mag('c', Magnitude(2.99792458e8, m=1, s=-1))

      # Acceleration
      new_mag('gravity', Magnitude(9.80665, m=1, s=-2))

Two magnitudes have no units, ’rad’ (radian - unit of plane angle) and ’sr’ (steradian - unit of solid angle).

Any of the above units can be augmented with the following set of scale prefixes:

  _prefix = {'y': 1e-24,  # yocto
             'z': 1e-21,  # zepto
             'a': 1e-18,  # atto
             'f': 1e-15,  # femto
             'p': 1e-12,  # pico
             'n': 1e-9,   # nano
             'u': 1e-6,   # micro
             'm': 1e-3,   # mili
             'c': 1e-2,   # centi
             'd': 1e-1,   # deci
             'k': 1e3,    # kilo
             'M': 1e6,    # mega
             'G': 1e9,    # giga
             'T': 1e12,   # tera
             'P': 1e15,   # peta
             'E': 1e18,   # exa
             'Z': 1e21,   # zetta
             'Y': 1e24,   # yotta

             # Binary prefixes, approved by the International
             # Electrotechnical Comission in 1998.  Since then, kb means
             # 1000 bytes; for 1024 bytes use Kib (note the capital K in
             # the binary version, and the lower case for the b of byte,
             # see comment in byte definition below).
             'Ki': 2 ** 10, # Kibi (<- kilo, 10^3)
             'Mi': 2 ** 20, # Mebi (<- mega, 10^6)
             'Gi': 2 ** 30, # Gibi (<- giga, 10^9)
             'Ti': 2 ** 40, # Tebi (<- tera, 10^12)
             'Pi': 2 ** 50, # Pebi (<- peta, 10^15)
             'Ei': 2 ** 60  # Exbi (<- exa, 10^18)

Exported symbols

  • Magnitude [class] — Numbers with units; math operations are overloaded
  • mg(number, unit, ounit=’’) — Construct a Magnitude
  • ensmg(m, unit=’’) — Tries to build a Magnitude out of something
  • newmag(indicator, mag) — Intern a new magnitude with its name
  • MagnitudeError [class] — Magnitude error handling

Defining new magnitudes

You can define new magnitudes by instantiating the Magnitude class. Suppose you want to define pounds as a magnitude and associate with it the unit ’lb’. A pound is 0.45359237 kilograms, so we have

      >>> lb = Magnitude(0.45359237, kg=1)

To make it recognized automatically you also have to introduce it to the system with new_mag. You can then use it as you would any other predefined physical quantity:

      >>> new_mag('lb', lb)
      >>> me = mg(180, 'lb')
      >>> print me.ounit('kg').toval()
      >>> new_mag('mile', mg(160934.4, 'cm'))
      >>> print mg(100, 'mile/h').ounit('km/h')
      160.9344 km/h

Bits and bytes (2009-11-03)

A previous version of the library used “bit” for bit and “b” for byte, leaving B for Bel. Following Michael Scheper’s suggestion we follow now IEEE 1541 and use “b” for bit and “B” for byte. If the need arises I’ll implement ad-hoc esupport for dB, but for the time being there is none.

More on units

Alternative unit libraries for Python

I haven’t tested them; I wrote these comments several years ago after looking at the documentation.

  1. Unum looks well finished and is thoroughly documented. Good: allows you to define arbitrary units (magnitude only supports user-defined units as long as they are a combination of the base units). Bad: it looks like it doesn’t handle prefixes, and it clutters your namespace with all its unit definitions (you end up with variables named M, S, etc. in your namespace).
  2. Scalar looks very similar to Unum, maybe not as well documented. Looks like it has exactly the same problems and advantages, plus the ability of running with units disabled (which should be good for performance).
  3. PhyisicalQuantities, part of ScientificPython, is very similar to magnitude. Same approach, essentially the same functionality, very similar API. Looks like it also clutters your namespace with unit names.
Juan Reyero Barcelona, 2009-11-07


blog comments powered by Disqus