# pyqn

pyqn is a Python 3 package for handling physical quantities with names, values, uncertainties and units. It is hosted on github and is available as free software under the GPL-v3 open source licence.

### Units

The units of a physical quantity are represented by a Units object, which has methods for deducing the dimensions of a set of units and for calculating conversion factors between units. The simplest Units, expressed as a string are simply the commonly-used unit symbols such as m (metre), Pa (pascal), Å (Ångstrom), and Hz (hertz). Click here for a full list of recognised units.

These simple units can carry any of the SI prefixes between y (yocto, 10-24) and Y (yotta, 10+24). For example, nm (nanometres), kg (kilograms), GHz (gigahertz), and μs (microseconds). Note that unit strings are represented as unicode strings encoded as UTF-8 throughout the pyqn package. They can be raised to any integer power by placing the exponent to the right of the unit symbol, as in J2 (joules squared) and cm-1 (inverse centimetres). Note that no exponentiation operator such as ^ or ** is used.

Units are combined by indicating multiplication by a period ('.') and division by a solidus ('/'). Note that a maximum of one units division is supported, and parentheses are not implemented (yet). Some examples are: g.mol-1 (grams per mole), kg.m.s-2 (kilogram metres per second per second) and V/m (volts per metre). Different Units objects can be further combined using the usual Python mathematical operators, * and /:

In [1]: from pyqn.units import Units

In [2]: u1 = Units('km')

In [3]: u2 = Units('hr')

In [4]: u3 = u1/u2

In [5]: print(u3)
km.hr-1

Units can be converted from one system to another using the conversion method to return the conversion factor, only if both systems have the same dimensions:

In [6]: u4 = Units('m/s')

In [7]: u3.conversion(u4)        # OK: can convert from km/hr to m/s
Out[7]: 0.2777777777777778

In [8]: u3.conversion(u2)        #  Oops: can't convert from km/hr to m!
...
UnitsError: Failure in units conversion: units km.hr-1[L.T-1] and hr[T] have
different dimensions

The conversion method also accepts a string argument so the valid conversion above is equivalent to:

In [9]: u3.conversion('m/s')
Out[9]: 0.2777777777777778

It is also possible to convert between units without creating a Units object at all, using the convenience method convert:

In [10]: from pyqn.units import convert

In [11]: convert('km/hr', 'm/s')
Out[11]: 0.2777777777777778

In [12]: 299792458 * convert('m/s', 'fur/ftn')
Out[12]: 1802617499785.2542    # speed of light in furlongs per fortnight

### Physical Quantities

The Quantity class, found in the pyqn.quantity module, provides a simple representation of physical quantities with a name, value, units, uncertainty and description.

#### Creating a pyqn Quantity

The complete initialization method for Quantity objects allows one to set the Quantity's plain-text name (name), LaTeX representation (latex), HTML representation (html), value (value, a floating-point number), units (units, either a text string to be parsed, or a Units object), uncertainty (sd, expressed as a 1σ standard deviation), and description or definition (definition). For example,

Mr = Quantity ('M_EtOH',
r'$M_\mathrm{EtOH}$',
'<em>M</em><sub>EtOH</sub>',
44.01,
'g.mol-1',
0.012,
'molar mass of ethanol')

It is not necessary to set all (or any) of these attributes:

k = Quantity(name='k', value=2300., units='N/m',
definition='N2 bond force constant')

#### Parsing pyqn Quantities

pyqn will do its best to parse a plain text string into a Quantity object. Quantity names are assigned in this string with name =, uncertainties given as an integer value in parentheses at the appropriate significant figure after the value, and units as a string separated from the value/sd by whitespace. Scientific notation is supported with the exponent denoted by one of e, E, d or D). For example,

Mr = Quantity.parse('Mr = 44.010(12) g.mol-1')
k = Quantity.parse('k = 2.3e3 N/m')
x = Quantity.parse('400')

#### Outputing pyqn Quantities

In addition to the usual __str__() method, which returns a string representation of the Quantity object with its name and units (if defined), there is also a method, as_str(), which takes boolean arguments, b_name, b_sd and b_units to control which of the Quantity's name, uncertainty and units should be output in the returned string. For example,

>>> g = Quantity.parse('g = 9.818(7) m.s-2')
>>> print(g.as_str())   # by default, output name, sd and units
g = 9.818(7) m.s-2
>>> print(g.as_str(b_sd=False))
g = 9.818 m.s-2
>>> print(g.as_str(b_name=False, b_sd=False))
9.818 m.s-2

#### Quantity Algebra

Quantity objects support simple algebra (addition, subtraction, multiplication and division). Errors (i.e. standard deviation uncertainties) are propagated, but assumed to be uncorrelated. Note that addition and subtraction can only be carried out with Quantity operands with the same units (not just the same dimensions). For example,

>>> DeltaH = Quantity.parse('DeltaH = 47.15(4) kJ.mol-1')
>>> T = Quantity(name='T', units='K', value=298., sd=0.5)
>>> DeltaS = DeltaH / T   # DeltaS now has units kJ.K-1.mol-1
>>> DeltaS.convert_units_to('J.K-1.mol-1')
>>> print(DeltaS.as_str())
158.22(30) J.K-1.mol-1