diff --git a/README.rst b/README.rst
index f5c6fe8..6e7ca91 100644
--- a/README.rst
+++ b/README.rst
@@ -10,59 +10,3 @@ transforming physical quantities and their units.
Units are specified as strings using a simple and flexible syntax,
and may be compared, output in different formats and manipulated using a
variety of predefined Python methods.
-
-
-
-Installation:
-=============
-
-The PyQn package can be installed either from PyPI_ using pip
-
-.. code-block:: bash
-
- python3 -m pip install pyqn
-
-or from the source by running (one of the two) from the project source directory.
-
-.. code-block:: bash
-
- # either
- python setup.py install
-
- # or
- python3 -m pip install .
-
-
-
-Examples:
-=========
-
-Units
------
-The units of physical quantities are represented by the ``Units`` class. A
-``Units`` object is instantiated from a valid units string and supports ions,
-isotopologues, as well as a few special species. This object contains
-attributes including the dimensions, HTML and LaTeX representations, and
-methods for conversion to different compatible units.
-
-.. code-block:: pycon
-
- >>> from pyqn.units import Units
- >>> u1 = Units('km')
-
- >>> u2 = Units('hr')
-
- >>> u3 = u1/u2
-
- >>> print(u3)
- km.hr-1
-
- >>> u4 = Units('m/s')
-
- >>> u3.conversion(u4) # OK: can convert from km/hr to m/s
- Out[7]: 0.2777777777777778
-
- >>> 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
diff --git a/setup.py b/setup.py
index ea1e683..f3a66c1 100644
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@
setup(
name="pyqn",
- version="1.3",
+ version="1.3.2",
description="A package for managing physical units and quantities",
long_description=long_description,
long_description_content_type="text/x-rst",
@@ -40,7 +40,7 @@
],
extras_require={"dev": ["black", "pytest-cov", "tox", "ipython"]},
# package_data will include all the resolved globs into both the wheel and sdist
- #package_data={},
+ # package_data={},
# no need for MANIFEST.in, which should be reserved only for build-time files
project_urls={
"Bug Reports": "https://github.com/xnx/pyqn/issues",
diff --git a/src/pyqn/atom_unit.py b/src/pyqn/atom_unit.py
index 6485ca5..f148149 100644
--- a/src/pyqn/atom_unit.py
+++ b/src/pyqn/atom_unit.py
@@ -23,39 +23,45 @@
# along with PyQn. If not, see
import sys
-from pyparsing import Word, Group, Literal, Suppress, ParseException, oneOf,\
- Optional
+from pyparsing import Word, Group, Literal, Suppress, ParseException, oneOf, Optional
from .si import si_prefixes
from .base_unit import BaseUnit, base_unit_stems
from .dimensions import Dimensions
# pyparsing stuff for parsing unit strings:
-caps = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+caps = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lowers = caps.lower()
-letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0'
-digits = '123456789'
-exponent = Word(digits + '-')
+letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0"
+digits = "123456789"
+exponent = Word(digits + "-")
prefix = oneOf(list(si_prefixes.keys()))
-ustem = Word(letters + 'Å' + 'Ω')
-uatom = (Group( '1' | (Optional(prefix) + ustem)) + Optional(exponent))\
- | (Group( '1' | ustem) + Optional(exponent))
+ustem = Word(letters + "Å" + "Ω")
+uatom = (Group("1" | (Optional(prefix) + ustem)) + Optional(exponent)) | (
+ Group("1" | ustem) + Optional(exponent)
+)
# floating point equality and its negation, to some suitable tolerance
-def feq(f1, f2, tol=1.e-10):
- return abs(f1-f2) <= tol
-def fneq(f1, f2, tol=1.e-10):
+def feq(f1, f2, tol=1.0e-10):
+ return abs(f1 - f2) <= tol
+
+
+def fneq(f1, f2, tol=1.0e-10):
return not feq(f1, f2, tol)
+
class UnitsError(Exception):
"""
An Exception class for errors that might occur whilst manipulating units.
"""
+
def __init__(self, error_str):
self.error_str = error_str
+
def __str__(self):
return self.error_str
+
class AtomUnit(object):
"""
AtomUnit is a class to represent a single BaseUnit, possibly with an SI
@@ -64,22 +70,21 @@ class AtomUnit(object):
"""
def __init__(self, prefix, base_unit, exponent=1):
- """ Initialize the AtomUnit object. """
+ """Initialize the AtomUnit object."""
self.base_unit = base_unit
self.exponent = exponent
- self.dims = self.base_unit.dims ** self.exponent
+ self.dims = self.base_unit.dims**self.exponent
# get the SI prefix (if present), and its 'factor' (10 raised to its
# the power it represents
- self.si_fac = 1.
+ self.si_fac = 1.0
self.prefix = prefix
if prefix is not None:
try:
self.si_prefix = si_prefixes[prefix]
except KeyError:
- raise UnitsError('Invalid or unsupported SI prefix: %s'
- % prefix)
+ raise UnitsError("Invalid or unsupported SI prefix: %s" % prefix)
self.si_fac = self.si_prefix.fac
# now calculate the factor relating this AtomUnit to its
# corresponding SI unit:
@@ -97,7 +102,7 @@ def parse(self, s_unit_atom):
uatom_data = uatom.parseString(s_unit_atom)
except ParseException:
raise
- raise UnitsError('Invalid unit atom syntax: %s' % s_unit_atom)
+ raise UnitsError("Invalid unit atom syntax: %s" % s_unit_atom)
# uatom_data comes back as (([prefix], ), [exponent])
if len(uatom_data[0]) == 1:
@@ -111,7 +116,7 @@ def parse(self, s_unit_atom):
# properly (ie to mmHg, not to milli-mHg):
if stem not in base_unit_stems:
prefix = None
- stem = ''.join(uatom_data[0])
+ stem = "".join(uatom_data[0])
try:
base_unit = base_unit_stems[stem]
except:
@@ -124,18 +129,18 @@ def parse(self, s_unit_atom):
return AtomUnit(prefix, base_unit, exponent)
def __pow__(self, power):
- """ Return the current AtomUnit raised to a specified power. """
+ """Return the current AtomUnit raised to a specified power."""
return AtomUnit(self.prefix, self.base_unit, self.exponent * power)
def __str__(self):
- """ String representation of this AtomUnit. """
- s = ''
+ """String representation of this AtomUnit."""
+ s = ""
if self.prefix:
s = self.prefix
- s_exponent = ''
+ s_exponent = ""
if self.exponent != 1:
s_exponent = str(self.exponent)
- return ''.join([s, str(self.base_unit), s_exponent])
+ return "".join([s, str(self.base_unit), s_exponent])
def __repr__(self):
return str(self)
@@ -150,4 +155,3 @@ def prefix_base_eq(self, other):
if self.prefix == other.prefix and self.base_unit == other.base_unit:
return True
return False
-
diff --git a/src/pyqn/base_unit.py b/src/pyqn/base_unit.py
index 833c4a7..e59b8f5 100644
--- a/src/pyqn/base_unit.py
+++ b/src/pyqn/base_unit.py
@@ -23,18 +23,18 @@
from .dimensions import *
+
class BaseUnit(object):
"""
A BaseUnit is a commonly-used single unit without a prefix, for example:
m (metre, length), erg (energy), bar (pressure). BaseUnit objects have
a description and know their dimensions in terms of powers of Length,
- Time, Mass, etc. (described by a Dimensions object).
+ Time, Mass, etc. (described by a Dimensions object).
"""
- def __init__(self, stem, name, unit_type, fac, description, latex,
- dims=None):
- """ Initialize the BaseUnit object. """
+ def __init__(self, stem, name, unit_type, fac, description, latex, dims=None):
+ """Initialize the BaseUnit object."""
# BaseUnit stem, e.g. 'm', 'g', 'bar', ...
self.stem = stem
# BaseUnit name, e.g. 'metre', 'gram', 'bar', ...
@@ -57,154 +57,300 @@ def __eq__(self, other):
return True
def __str__(self):
- """ String representation of the BaseUnit is just its 'stem'. """
+ """String representation of the BaseUnit is just its 'stem'."""
return self.stem
-base_units = (
-('Unity', [
-BaseUnit('1', 'unity', 'unity', 1., '', '1', d_dimensionless),
-]),
-
-('SI unit stems', [
-BaseUnit('m', 'metre', 'length', 1., '', 'm', d_length),
-BaseUnit('s', 'second', 'time', 1., '', 's', d_time),
-BaseUnit('g', 'gram', 'mass', 1.e-3, '', 'g', d_mass),
-BaseUnit('K', 'kelvin', 'temperature', 1., '', 'K', Dimensions(Theta=1)),
-BaseUnit('mol', 'mole', 'amount', 1., '', 'mol', Dimensions(Q=1)),
-BaseUnit('A', 'amp', 'current', 1., '', 'A', Dimensions(C=1)),
-BaseUnit('cd', 'candela', 'luminous intensity', 1., '', 'cd', Dimensions(I=1))
-]),
-
-('Derived SI units', [
-BaseUnit('N', 'newton', 'force', 1., '', 'N', d_force),
-BaseUnit('J', 'joule', 'energy', 1., '', 'J', d_energy),
-BaseUnit('W', 'watt', 'power', 1., '', 'W', d_energy / d_time),
-BaseUnit('Pa', 'pascal', 'pressure', 1., '', 'Pa', d_pressure),
-BaseUnit('C', 'coulomb', 'charge', 1., '', 'C', d_charge),
-BaseUnit('V', 'volt', 'voltage', 1., '', 'V', d_voltage),
-BaseUnit('Ω', 'ohm', 'electric resistance', 1, '', r'\Omega',
- d_voltage / d_current),
-BaseUnit('F', 'farad', 'capacitance', 1., '', 'F', d_charge / d_voltage),
-BaseUnit('Wb', 'weber', 'magnetic flux', 1, '', 'Wb', d_magnetic_flux),
-BaseUnit('H', 'henry', 'inductance', 1, '', 'H', d_magnetic_flux / d_current),
-BaseUnit('S', 'siemens', 'electric conductance', 1, '', 'S',
- d_current / d_voltage),
-BaseUnit('T', 'tesla', 'magnetic field strength', 1., '', 'T',
- d_magfield_strength),
-BaseUnit('Hz', 'hertz', 'cyclic frequency', 1., '', 'Hz', d_time**-1),
-BaseUnit('rad', 'radian', 'angle', 1., '', 'rad', d_dimensionless),
-BaseUnit('sr', 'steradian', 'solid angle', 1., '', 'sr', d_dimensionless),
-]),
-
-('Non-SI pressure units', [
-BaseUnit('bar', 'bar', 'pressure', 1.e5, '', 'bar', d_pressure),
-BaseUnit('atm', 'atmosphere', 'pressure', 1.01325e5, '', 'atm', d_pressure),
-BaseUnit('Torr', 'torr', 'pressure', 133.322368, '', 'Torr', d_pressure),
-# (but see e.g. Wikipedia for the precise relationship between Torr and mmHg
-BaseUnit('mmHg', 'millimetres of mercury', 'pressure', 133.322368, '', 'mmHg',
- d_pressure),
-]),
-
-('cgs units', [
-BaseUnit('dyn', 'dyne', 'force', 1.e-5, '', 'dyn', d_force),
-BaseUnit('erg', 'erg', 'energy', 1.e-7, '', 'erg', d_energy),
-BaseUnit('k', 'kayser', 'wavenumber', 100., '', 'k', d_length**-1),
-BaseUnit('D', 'debye', 'electric dipole moment', 1.e-21/299792458., '', 'D',
- d_charge * d_length),
-BaseUnit('hbar', 'hbar', 'angular momentum', 1.05457148e-34, '', r'\hbar',
- Dimensions(L=2, M=1, T=-1)),
-BaseUnit('e', 'electron charge', 'charge', 1.602176565e-19, '', 'e', d_charge),
-]),
-
-('Angular units', [
-BaseUnit('deg', 'degree', 'angle', 0.017453292519943295, '', 'deg',
- d_dimensionless),
-BaseUnit('arcmin', 'arcminute', 'angle', 2.908882086657216e-4, '', 'arcmin',
- d_dimensionless),
-# NB we can't allow 'as' for arcseconds because of ambiguity with attoseconds
-BaseUnit('asec', 'arcsecond', 'angle', 4.84813681109536e-6, '', 'asec',
- d_dimensionless),
-]),
-
-('Non-SI energy units', [
-BaseUnit('eV', 'electron volt', 'energy', 1.602176487e-19, '', 'eV',
- d_energy),
-BaseUnit('E_h', 'hartree', 'energy', 4.35974394e-18, '', 'E_h', d_energy),
-BaseUnit('cal', 'thermodynamic calorie', 'energy', 4.184, '', 'cal', d_energy),
-BaseUnit('Ry', 'rydberg', 'energy', 13.60569253 * 1.602176487e-19, '', 'Ry',
- d_energy),
-]),
-
-('Non-SI mass units', [
-BaseUnit('u', 'atomic mass unit', 'mass', 1.660538921e-27, '', 'u', d_mass),
-BaseUnit('amu', 'atomic mass unit', 'mass', 1.660538921e-27, '', 'am', d_mass),
-BaseUnit('Da', 'dalton', 'mass', 1.660538921e-27, '', 'Da', d_mass),
-BaseUnit('m_e', 'electron mass', 'mass', 9.10938291e-31, '', 'm_e', d_mass),
-]),
-('Non-SI units of length, area and volume', [
-# Non-SI length units
-BaseUnit('Å', 'angstrom', 'length', 1.e-10, '', r'\AA', d_length),
-BaseUnit('a0', 'bohr', 'length', 5.2917721092e-11, '', 'a_0', d_length),
-# Non-SI area units
-BaseUnit('b', 'barn', 'area', 1.e-28, '', 'b', d_area),
-# Non-SI volume units
-BaseUnit('l', 'litre', 'volume', 1.e-3, '', 'l', d_volume),
-BaseUnit('L', 'litre', 'volume', 1.e-3, '', 'L', d_volume),
-]),
-
-('Non-SI time units', [
-BaseUnit('min', 'minute', 'time', 60., '', 'min', d_time),
-BaseUnit('hr', 'hour', 'time', 3600., '', 'hr', d_time),
-BaseUnit('h', 'hour', 'time', 3600., '', 'h', d_time),
-BaseUnit('dy', 'day', 'time', 86400., '', 'd', d_time),
-BaseUnit('yr', 'year', 'time', 31557600., '', 'yr', d_time),
-]),
-
-('Astronomical units', [
-BaseUnit('AU', 'astronomical unit', 'length', 1.495978707e11, '', 'AU',
- d_length),
-BaseUnit('pc', 'parsec', 'length', 3.085677637634e16, '', 'pc', d_length),
-BaseUnit('ly', 'light-year', 'length', 9.4607304725808e15, '', 'ly', d_length),
-]),
-
-('Imperial, customary and US units', [
-# NB we can't use 'in' for inch because of a clash with min
-BaseUnit('inch', 'inch', 'length', 0.0254, '', 'in', d_length),
-BaseUnit('ft', 'foot', 'length', .3048, '', 'ft', d_length),
-# NB we can't use 'yd' for yard because of a clash with yd (yoctodays!)
-BaseUnit('yard', 'yard', 'length', .9144, '', 'yd', d_length),
-BaseUnit('fur', 'furlong', 'length', 201.168, '', 'furlong', d_length),
-BaseUnit('mi', 'mile', 'length', 1609.344, '', 'mi', d_length),
-BaseUnit('gal', 'Imperial (UK) gallon', 'volume', 4.54609e-3, '', 'gal',
- d_volume),
-BaseUnit('pt', 'Imperial (UK) pint', 'volume', 5.6826125e-4, '', 'pt',
- d_volume),
-BaseUnit('USgal', 'US liquid gallon', 'volume', 3.785411783e-3, '', 'USgal',
- d_volume),
-BaseUnit('USpt', 'US liquid pint', 'volume', 4.73176472875e-4, '', 'USpt',
- d_volume),
-BaseUnit('st', 'stone', 'mass', 6.35029318, '', 'st', d_mass),
-BaseUnit('lb', 'pound', 'mass', 0.45359237, '', 'lb', d_mass),
-BaseUnit('oz', 'ounce', 'mass', 0.028349523125, '', 'oz', d_mass),
-]),
-
-('Maritime units', [
-BaseUnit('NM', 'nautical mile', 'length', 1852., '', 'NM', d_length),
-BaseUnit('kn', 'knot', 'speed', 1852., '', 'kn', d_length/d_time),
-]),
-
-('Silly units', [
-BaseUnit('fir', 'fikin', 'mass', 40.8233133, '', 'fir', d_mass),
-BaseUnit('ftn', 'fortnight', 'time', 1.2096e6, '', 'ftn', d_time),
-]),
-
-('Miscellaneous units', [
-BaseUnit('Td', 'townsend', 'reduced electric field', 1.e-21, '', 'Td',
- d_voltage * d_area),
-BaseUnit('Jy', 'jansky', 'spectral flux density', 1.e-26, '', 'Jy',
- d_energy / d_area) # W.m-2.s-1
-]),
+base_units = (
+ (
+ "Unity",
+ [
+ BaseUnit("1", "unity", "unity", 1.0, "", "1", d_dimensionless),
+ ],
+ ),
+ (
+ "SI unit stems",
+ [
+ BaseUnit("m", "metre", "length", 1.0, "", "m", d_length),
+ BaseUnit("s", "second", "time", 1.0, "", "s", d_time),
+ BaseUnit("g", "gram", "mass", 1.0e-3, "", "g", d_mass),
+ BaseUnit("K", "kelvin", "temperature", 1.0, "", "K", Dimensions(Theta=1)),
+ BaseUnit("mol", "mole", "amount", 1.0, "", "mol", Dimensions(Q=1)),
+ BaseUnit("A", "amp", "current", 1.0, "", "A", Dimensions(C=1)),
+ BaseUnit(
+ "cd", "candela", "luminous intensity", 1.0, "", "cd", Dimensions(I=1)
+ ),
+ ],
+ ),
+ (
+ "Derived SI units",
+ [
+ BaseUnit("N", "newton", "force", 1.0, "", "N", d_force),
+ BaseUnit("J", "joule", "energy", 1.0, "", "J", d_energy),
+ BaseUnit("W", "watt", "power", 1.0, "", "W", d_energy / d_time),
+ BaseUnit("Pa", "pascal", "pressure", 1.0, "", "Pa", d_pressure),
+ BaseUnit("C", "coulomb", "charge", 1.0, "", "C", d_charge),
+ BaseUnit("V", "volt", "voltage", 1.0, "", "V", d_voltage),
+ BaseUnit(
+ "Ω",
+ "ohm",
+ "electric resistance",
+ 1,
+ "",
+ r"\Omega",
+ d_voltage / d_current,
+ ),
+ BaseUnit("F", "farad", "capacitance", 1.0, "", "F", d_charge / d_voltage),
+ BaseUnit("Wb", "weber", "magnetic flux", 1, "", "Wb", d_magnetic_flux),
+ BaseUnit(
+ "H", "henry", "inductance", 1, "", "H", d_magnetic_flux / d_current
+ ),
+ BaseUnit(
+ "S",
+ "siemens",
+ "electric conductance",
+ 1,
+ "",
+ "S",
+ d_current / d_voltage,
+ ),
+ BaseUnit(
+ "T",
+ "tesla",
+ "magnetic field strength",
+ 1.0,
+ "",
+ "T",
+ d_magfield_strength,
+ ),
+ BaseUnit("Hz", "hertz", "cyclic frequency", 1.0, "", "Hz", d_time**-1),
+ BaseUnit("rad", "radian", "angle", 1.0, "", "rad", d_dimensionless),
+ BaseUnit("sr", "steradian", "solid angle", 1.0, "", "sr", d_dimensionless),
+ ],
+ ),
+ (
+ "Non-SI pressure units",
+ [
+ BaseUnit("bar", "bar", "pressure", 1.0e5, "", "bar", d_pressure),
+ BaseUnit("atm", "atmosphere", "pressure", 1.01325e5, "", "atm", d_pressure),
+ BaseUnit("Torr", "torr", "pressure", 133.322368, "", "Torr", d_pressure),
+ # (but see e.g. Wikipedia for the precise relationship between Torr and mmHg
+ BaseUnit(
+ "mmHg",
+ "millimetres of mercury",
+ "pressure",
+ 133.322368,
+ "",
+ "mmHg",
+ d_pressure,
+ ),
+ ],
+ ),
+ (
+ "cgs units",
+ [
+ BaseUnit("dyn", "dyne", "force", 1.0e-5, "", "dyn", d_force),
+ BaseUnit("erg", "erg", "energy", 1.0e-7, "", "erg", d_energy),
+ BaseUnit("k", "kayser", "wavenumber", 100.0, "", "k", d_length**-1),
+ BaseUnit(
+ "D",
+ "debye",
+ "electric dipole moment",
+ 1.0e-21 / 299792458.0,
+ "",
+ "D",
+ d_charge * d_length,
+ ),
+ BaseUnit(
+ "hbar",
+ "hbar",
+ "angular momentum",
+ 1.05457148e-34,
+ "",
+ r"\hbar",
+ Dimensions(L=2, M=1, T=-1),
+ ),
+ BaseUnit(
+ "e", "electron charge", "charge", 1.602176565e-19, "", "e", d_charge
+ ),
+ ],
+ ),
+ (
+ "Angular units",
+ [
+ BaseUnit(
+ "deg",
+ "degree",
+ "angle",
+ 0.017453292519943295,
+ "",
+ "deg",
+ d_dimensionless,
+ ),
+ BaseUnit(
+ "arcmin",
+ "arcminute",
+ "angle",
+ 2.908882086657216e-4,
+ "",
+ "arcmin",
+ d_dimensionless,
+ ),
+ # NB we can't allow 'as' for arcseconds because of ambiguity with attoseconds
+ BaseUnit(
+ "asec",
+ "arcsecond",
+ "angle",
+ 4.84813681109536e-6,
+ "",
+ "asec",
+ d_dimensionless,
+ ),
+ ],
+ ),
+ (
+ "Non-SI energy units",
+ [
+ BaseUnit(
+ "eV", "electron volt", "energy", 1.602176487e-19, "", "eV", d_energy
+ ),
+ BaseUnit("E_h", "hartree", "energy", 4.35974394e-18, "", "E_h", d_energy),
+ BaseUnit(
+ "cal", "thermodynamic calorie", "energy", 4.184, "", "cal", d_energy
+ ),
+ BaseUnit(
+ "Ry",
+ "rydberg",
+ "energy",
+ 13.60569253 * 1.602176487e-19,
+ "",
+ "Ry",
+ d_energy,
+ ),
+ ],
+ ),
+ (
+ "Non-SI mass units",
+ [
+ BaseUnit("u", "atomic mass unit", "mass", 1.660538921e-27, "", "u", d_mass),
+ BaseUnit(
+ "amu", "atomic mass unit", "mass", 1.660538921e-27, "", "am", d_mass
+ ),
+ BaseUnit("Da", "dalton", "mass", 1.660538921e-27, "", "Da", d_mass),
+ BaseUnit("m_e", "electron mass", "mass", 9.10938291e-31, "", "m_e", d_mass),
+ ],
+ ),
+ (
+ "Non-SI units of length, area and volume",
+ [
+ # Non-SI length units
+ BaseUnit("Å", "angstrom", "length", 1.0e-10, "", r"\AA", d_length),
+ BaseUnit("a0", "bohr", "length", 5.2917721092e-11, "", "a_0", d_length),
+ # Non-SI area units
+ BaseUnit("b", "barn", "area", 1.0e-28, "", "b", d_area),
+ # Non-SI volume units
+ BaseUnit("l", "litre", "volume", 1.0e-3, "", "l", d_volume),
+ BaseUnit("L", "litre", "volume", 1.0e-3, "", "L", d_volume),
+ ],
+ ),
+ (
+ "Non-SI time units",
+ [
+ BaseUnit("min", "minute", "time", 60.0, "", "min", d_time),
+ BaseUnit("hr", "hour", "time", 3600.0, "", "hr", d_time),
+ BaseUnit("h", "hour", "time", 3600.0, "", "h", d_time),
+ BaseUnit("dy", "day", "time", 86400.0, "", "d", d_time),
+ BaseUnit("yr", "year", "time", 31557600.0, "", "yr", d_time),
+ ],
+ ),
+ (
+ "Astronomical units",
+ [
+ BaseUnit(
+ "AU", "astronomical unit", "length", 1.495978707e11, "", "AU", d_length
+ ),
+ BaseUnit("pc", "parsec", "length", 3.085677637634e16, "", "pc", d_length),
+ BaseUnit(
+ "ly", "light-year", "length", 9.4607304725808e15, "", "ly", d_length
+ ),
+ ],
+ ),
+ (
+ "Imperial, customary and US units",
+ [
+ # NB we can't use 'in' for inch because of a clash with min
+ BaseUnit("inch", "inch", "length", 0.0254, "", "in", d_length),
+ BaseUnit("ft", "foot", "length", 0.3048, "", "ft", d_length),
+ # NB we can't use 'yd' for yard because of a clash with yd (yoctodays!)
+ BaseUnit("yard", "yard", "length", 0.9144, "", "yd", d_length),
+ BaseUnit("fur", "furlong", "length", 201.168, "", "furlong", d_length),
+ BaseUnit("mi", "mile", "length", 1609.344, "", "mi", d_length),
+ BaseUnit(
+ "gal", "Imperial (UK) gallon", "volume", 4.54609e-3, "", "gal", d_volume
+ ),
+ BaseUnit(
+ "pt", "Imperial (UK) pint", "volume", 5.6826125e-4, "", "pt", d_volume
+ ),
+ BaseUnit(
+ "USgal",
+ "US liquid gallon",
+ "volume",
+ 3.785411783e-3,
+ "",
+ "USgal",
+ d_volume,
+ ),
+ BaseUnit(
+ "USpt",
+ "US liquid pint",
+ "volume",
+ 4.73176472875e-4,
+ "",
+ "USpt",
+ d_volume,
+ ),
+ BaseUnit("st", "stone", "mass", 6.35029318, "", "st", d_mass),
+ BaseUnit("lb", "pound", "mass", 0.45359237, "", "lb", d_mass),
+ BaseUnit("oz", "ounce", "mass", 0.028349523125, "", "oz", d_mass),
+ ],
+ ),
+ (
+ "Maritime units",
+ [
+ BaseUnit("NM", "nautical mile", "length", 1852.0, "", "NM", d_length),
+ BaseUnit("kn", "knot", "speed", 1852.0, "", "kn", d_length / d_time),
+ ],
+ ),
+ (
+ "Silly units",
+ [
+ BaseUnit("fir", "fikin", "mass", 40.8233133, "", "fir", d_mass),
+ BaseUnit("ftn", "fortnight", "time", 1.2096e6, "", "ftn", d_time),
+ ],
+ ),
+ (
+ "Miscellaneous units",
+ [
+ BaseUnit(
+ "Td",
+ "townsend",
+ "reduced electric field",
+ 1.0e-21,
+ "",
+ "Td",
+ d_voltage * d_area,
+ ),
+ BaseUnit(
+ "Jy",
+ "jansky",
+ "spectral flux density",
+ 1.0e-26,
+ "",
+ "Jy",
+ d_energy / d_area,
+ ), # W.m-2.s-1
+ ],
+ ),
)
# create a dictionary mapping the BaseUnit stems (as keys) to the BaseUnit
@@ -212,4 +358,3 @@ def __str__(self):
for base_unit_group in base_units:
for base_unit in base_unit_group[1]:
base_unit_stems[base_unit.stem] = base_unit
-
diff --git a/src/pyqn/dimensions.py b/src/pyqn/dimensions.py
index 168c250..ecaf6fb 100644
--- a/src/pyqn/dimensions.py
+++ b/src/pyqn/dimensions.py
@@ -22,24 +22,32 @@
# You should have received a copy of the GNU General Public License
# along with PyQn. If not, see
+
class Dimensions(object):
# these are the abbreviations for Length, Mass, Time, Temperature,
- # Quantity (amount of substance), Current, and Luminous Intensity:
- dim_names = ['L', 'M', 'T', 'Theta', 'Q', 'C', 'I']
- dim_desc = ['length', 'mass', 'time', 'temperature', 'amount',
- 'current', 'luminous intensity']
+ # Quantity (amount of substance), Current, and Luminous Intensity:
+ dim_names = ["L", "M", "T", "Theta", "Q", "C", "I"]
+ dim_desc = [
+ "length",
+ "mass",
+ "time",
+ "temperature",
+ "amount",
+ "current",
+ "luminous intensity",
+ ]
dim_index = {}
for i, dim_name in enumerate(dim_names):
dim_index[dim_name] = i
def __init__(self, dims=None, **kwargs):
- self.dims = [0]*7
+ self.dims = [0] * 7
if dims:
# initialize by dims array
if not kwargs:
self.dims = dims
else:
- print('bad initialisation of Dimensions object')
+ print("bad initialisation of Dimensions object")
sys.exit(1)
else:
# initialize by keyword arguments
@@ -70,11 +78,11 @@ def __str__(self):
if self.dims[i] != 0:
this_s_dim = dim_name
if self.dims[i] != 1:
- this_s_dim += '%d' % self.dims[i]
+ this_s_dim += "%d" % self.dims[i]
s_dims.append(this_s_dim)
if len(s_dims) == 0:
- return '[dimensionless]'
- return '.'.join(s_dims)
+ return "[dimensionless]"
+ return ".".join(s_dims)
def __repr__(self):
return str(self.dims)
@@ -88,6 +96,7 @@ def __eq__(self, other):
def __ne__(self, other):
return not self.__eq__(other)
+
d_dimensionless = Dimensions()
d_quantity = Dimensions(Q=1)
d_frequency = Dimensions(T=-1)
@@ -101,7 +110,7 @@ def __ne__(self, other):
d_pressure = d_force / d_area
d_current = Dimensions(C=1)
d_charge = d_current * Dimensions(T=1)
-d_voltage = d_energy / d_charge # 1 V = 1 J/C
-d_magfield_strength = d_voltage * d_time / d_area # 1 T = 1 V.s/m^2
-d_magnetic_flux = d_voltage * d_time # 1 Wb = 1 V.s
-d_temperature = Dimensions(Theta=1)
\ No newline at end of file
+d_voltage = d_energy / d_charge # 1 V = 1 J/C
+d_magfield_strength = d_voltage * d_time / d_area # 1 T = 1 V.s/m^2
+d_magnetic_flux = d_voltage * d_time # 1 Wb = 1 V.s
+d_temperature = Dimensions(Theta=1)
diff --git a/src/pyqn/list_base_units.py b/src/pyqn/list_base_units.py
index 5ee2108..cab1cfd 100644
--- a/src/pyqn/list_base_units.py
+++ b/src/pyqn/list_base_units.py
@@ -2,40 +2,47 @@
import sys
from base_unit import base_units
+
def list_units_text():
for group_name, base_unit_group in base_units:
print()
print(group_name)
- print('='*len(group_name))
- print('{0:6s} {1:30s} {2:20s}'.format('Unit', 'Name', 'Dimensions'))
- print('{0:6s} {1:30s} {2:20s}'.format('----', '----', '----------'))
+ print("=" * len(group_name))
+ print("{0:6s} {1:30s} {2:20s}".format("Unit", "Name", "Dimensions"))
+ print("{0:6s} {1:30s} {2:20s}".format("----", "----", "----------"))
for base_unit in base_unit_group:
- print('{0:6s} {1:30s} {2:20s}'.format(unicode(base_unit.stem),
- base_unit.name, base_unit.dims))
+ print(
+ "{0:6s} {1:30s} {2:20s}".format(
+ unicode(base_unit.stem), base_unit.name, base_unit.dims
+ )
+ )
+
def list_units_html():
for group_name, base_unit_group in base_units:
- print('{0}
'.format(group_name))
+ print("{0}
".format(group_name))
print('')
- print('Unit | Name | Dimensions |
')
+ print("Unit | Name | Dimensions |
")
for base_unit in base_unit_group:
# NB we need to encode('utf-8') to pipe in that encoding to the
# shell, e.g. to create a file
- print('{0:s} | {1:s} | {2:s} | |
'
- .format(unicode(base_unit.stem), base_unit.name,
- base_unit.dims).encode('utf-8'))
- print('
')
-
+ print(
+ "{0:s} | {1:s} | {2:s} | |
".format(
+ unicode(base_unit.stem), base_unit.name, base_unit.dims
+ ).encode("utf-8")
+ )
+ print("")
+
try:
list_type = sys.argv[1]
- assert list_type in ('text', 'html')
+ assert list_type in ("text", "html")
except (IndexError, AssertionError):
- print('usage:\n{0} '.format(sys.argv[0]))
- print('where is text or html')
+ print("usage:\n{0} ".format(sys.argv[0]))
+ print("where is text or html")
sys.exit(1)
-if list_type == 'text':
+if list_type == "text":
list_units_text()
else:
list_units_html()
diff --git a/src/pyqn/qn_array.py b/src/pyqn/qn_array.py
index 7e4cbdb..d832b61 100644
--- a/src/pyqn/qn_array.py
+++ b/src/pyqn/qn_array.py
@@ -1,19 +1,30 @@
from .symbol import Symbol
import numpy as np
+
class qnArrayError(Exception):
def __init__(self, error_str):
self.error_str = error_str
+
def __str__(self):
return self.error_str
+
class qnArray(Symbol):
- def __init__(self, name=None, latex=None, html=None, values=None,
- units=None, sd=None, definition=None):
+ def __init__(
+ self,
+ name=None,
+ latex=None,
+ html=None,
+ values=None,
+ units=None,
+ sd=None,
+ definition=None,
+ ):
Symbol.__init__(self, name, latex, html, definition)
- if type(values)==list:
+ if type(values) == list:
self.values = np.array(values)
- elif type(values)==numpy.ndarray:
+ elif type(values) == numpy.ndarray:
self.values = values
else:
raise qnArrayError
diff --git a/src/pyqn/quantity.py b/src/pyqn/quantity.py
index 077a1ac..e913d91 100644
--- a/src/pyqn/quantity.py
+++ b/src/pyqn/quantity.py
@@ -22,21 +22,26 @@
import re
import math
-#import numpy as np
+
+# import numpy as np
from .symbol import Symbol
from .units import Units, UnitsError
+
class QuantityError(Exception):
"""
An Exception class for errors that might occur whilst manipulating
Quantity objects.
"""
+
def __init__(self, error_str):
self.error_str = error_str
+
def __str__(self):
return self.error_str
+
class Quantity(Symbol):
"""
A Python class representing a physical quantity. This class extends the
@@ -47,8 +52,16 @@ class Quantity(Symbol):
"""
- def __init__(self, name=None, latex=None, html=None, value=None,
- units=None, sd=None, definition=None):
+ def __init__(
+ self,
+ name=None,
+ latex=None,
+ html=None,
+ value=None,
+ units=None,
+ sd=None,
+ definition=None,
+ ):
"""
Initialize the Quantity object: set up its name as for the base,
Symbol class, and set the quantity's value, sd and units (which
@@ -66,16 +79,16 @@ def __init__(self, name=None, latex=None, html=None, value=None,
self.units = Units(units)
def __str__(self):
- """ A simple string representation of the Quantity. """
+ """A simple string representation of the Quantity."""
if self.name:
- return '%s = %s %s' % (self.name, self.value, self.units)
+ return "%s = %s %s" % (self.name, self.value, self.units)
else:
- return '%s %s' % (self.value, self.units)
-
+ return "%s %s" % (self.value, self.units)
+
__repr__ = __str__
- def value_as_str(self, nsd_digits=2, small=1.e-3, large=1.e5):
+ def value_as_str(self, nsd_digits=2, small=1.0e-3, large=1.0e5):
"""
Return a string representation of the parameter and its
standard deviation in the conventional format used in
@@ -84,13 +97,13 @@ def value_as_str(self, nsd_digits=2, small=1.e-3, large=1.e5):
0.04857623(71) for 4.857623e-2 +/- 7.1e-7
-0.412(40) for -0.412 +/- 0.04
1.7324(38)e7 for 17324000 +/- 380
-
+
Notes:
This routine has not been rigorously tested, because I wrote
it at 1am. Therefore, it would be a good idea to output the
raw parameter values and standard deviations somewhere as
well as using the output from this routine...
-
+
Arguments:
nsd_digits: the number of digits in the standard deviation
(the default is 2)
@@ -98,20 +111,20 @@ def value_as_str(self, nsd_digits=2, small=1.e-3, large=1.e5):
scientific notation (e)
large: parameter values larger than large are output in
scientific notation (e-)
-
+
"""
N, sd = self.value, self.sd
-
+
if not sd:
return str(N)
absN = abs(N)
- if (absN < small or absN > large) and absN != 0.:
+ if (absN < small or absN > large) and absN != 0.0:
# scientific notation
power = int(math.floor(math.log(absN, 10)))
N *= pow(10, -power)
sd *= pow(10, -power)
- dp = int(-math.log(sd,10))+nsd_digits
+ dp = int(-math.log(sd, 10)) + nsd_digits
if dp < 0:
dp = 0
sd_digits = int(round(sd * pow(10, dp)))
@@ -123,7 +136,7 @@ def value_as_str(self, nsd_digits=2, small=1.e-3, large=1.e5):
if dp < 0:
dp = 0
sd_digits = int(round(sd * pow(10, dp)))
- fmt = "%." + str(dp) + "f(" + str(sd_digits) + ')'
+ fmt = "%." + str(dp) + "f(" + str(sd_digits) + ")"
return fmt % N
@@ -136,14 +149,14 @@ def as_str(self, b_name=True, b_sd=True, b_units=True):
s = []
if b_name and self.name:
- s.append('%s = ' % self.name)
+ s.append("%s = " % self.name)
if b_sd:
s.append(self.value_as_str(b_sd))
else:
s.append(str(self.value))
if b_units and self.units.has_units():
- s.append(' %s' % str(self.units))
- return ''.join(s)
+ s.append(" %s" % str(self.units))
+ return "".join(s)
def convert_units_to(self, new_units, force=None):
"""
@@ -158,30 +171,30 @@ def convert_units_to(self, new_units, force=None):
to_units = Units(new_units)
fac = self.units.conversion(to_units, force)
-# self.value *= fac
-# if self.sd is not None:
-# self.sd *= fac
-# self.units = to_units
+ # self.value *= fac
+ # if self.sd is not None:
+ # self.sd *= fac
+ # self.units = to_units
if self.sd is not None:
- return Quantity(value = self.value*fac, units = new_units, sd = self.sd*fac)
+ return Quantity(value=self.value * fac, units=new_units, sd=self.sd * fac)
else:
- return Quantity(value = self.value*fac, units = new_units)
-
-# def draw_from_dist(self, shape=None):
-# """
-# Return a value or number array of values drawn from the normal
-# distribution described by this Quantity's mean and standard
-# deviation. shape is the shape of the NumPy array to return, or
-# None (the default) to return a single scalar value from the
-# distribution.
-#
-# """
-#
-# if self.sd is None:
-# raise ValueError('Quantity instance {} has no defined standard'
-# ' deviation.'.format(self.name))
-#
-# return np.random.normal(loc=self.value, scale=self.sd, size=shape)
+ return Quantity(value=self.value * fac, units=new_units)
+
+ # def draw_from_dist(self, shape=None):
+ # """
+ # Return a value or number array of values drawn from the normal
+ # distribution described by this Quantity's mean and standard
+ # deviation. shape is the shape of the NumPy array to return, or
+ # None (the default) to return a single scalar value from the
+ # distribution.
+ #
+ # """
+ #
+ # if self.sd is None:
+ # raise ValueError('Quantity instance {} has no defined standard'
+ # ' deviation.'.format(self.name))
+ #
+ # return np.random.normal(loc=self.value, scale=self.sd, size=shape)
def __add__(self, other):
"""
@@ -195,13 +208,15 @@ def __add__(self, other):
if self.value is None or other.value is None:
raise ValueError
if self.units != other.units:
- raise UnitsError('Can\'t add two quantities with different'
- ' units: %s and %s' % (self.units, other.units))
+ raise UnitsError(
+ "Can't add two quantities with different"
+ " units: %s and %s" % (self.units, other.units)
+ )
if self.sd is None or other.sd is None:
sd = None
else:
sd = math.hypot(self.sd, other.sd)
- return Quantity(value=self.value+other.value, units=self.units, sd=sd)
+ return Quantity(value=self.value + other.value, units=self.units, sd=sd)
def __sub__(self, other):
"""
@@ -215,13 +230,15 @@ def __sub__(self, other):
if self.value is None or other.value is None:
raise ValueError
if self.units != other.units:
- raise UnitsError('Can\'t subtract two quantities with different'
- ' units: %s and %s' % (self.units, other.units))
+ raise UnitsError(
+ "Can't subtract two quantities with different"
+ " units: %s and %s" % (self.units, other.units)
+ )
if self.sd is None or other.sd is None:
sd = None
else:
sd = math.hypot(self.sd, other.sd)
- return Quantity(value=self.value-other.value, units=self.units, sd=sd)
+ return Quantity(value=self.value - other.value, units=self.units, sd=sd)
def __mul__(self, other):
"""
@@ -237,7 +254,7 @@ def __mul__(self, other):
sd = None
else:
sd = abs(other) * self.sd
- return Quantity(value=self.value*other, units=self.unit, sd=sd)
+ return Quantity(value=self.value * other, units=self.unit, sd=sd)
else:
if type(other) != Quantity:
raise TypeError
@@ -247,8 +264,7 @@ def __mul__(self, other):
if not self.sd or not other.sd:
sd = None
else:
- sd = value * math.hypot(self.sd/self.value,
- other.sd/other.value)
+ sd = value * math.hypot(self.sd / self.value, other.sd / other.value)
units = self.units * other.units
return Quantity(value=value, units=units, sd=sd)
@@ -266,7 +282,7 @@ def __truediv__(self, other):
sd = None
else:
sd = abs(other) / self.sd
- return Quantity(value=self.value/other, units=self.units, sd=sd)
+ return Quantity(value=self.value / other, units=self.units, sd=sd)
else:
if type(other) != Quantity:
raise TypeError
@@ -276,54 +292,52 @@ def __truediv__(self, other):
if not self.sd or not other.sd:
sd = None
else:
- sd = value * math.hypot(self.sd/self.value,
- other.sd/other.value)
+ sd = value * math.hypot(self.sd / self.value, other.sd / other.value)
units = self.units / other.units
return Quantity(value=value, units=units, sd=sd)
def __rtruediv__(self, other):
return self.__truediv__(other)
-
+
def __pow__(self, power):
- return Quantity(value = self.value**power,
- units = self.units**power)
+ return Quantity(value=self.value**power, units=self.units**power)
@classmethod
- def parse(self, s_quantity, name=None, units=None, sd=None,
- definition=None):
+ def parse(self, s_quantity, name=None, units=None, sd=None, definition=None):
s_quantity = s_quantity.strip()
- if '=' in s_quantity:
- fields = s_quantity.split('=')
+ if "=" in s_quantity:
+ fields = s_quantity.split("=")
s_name = fields[0].strip()
if s_name:
name = s_name
s_quantity = fields[1].strip()
- fields = s_quantity.split(' ')
+ fields = s_quantity.split(" ")
s_valsd = fields[0]
if len(fields) == 2:
units = Units(fields[1])
# force lower case, and replace Fortran-style 'D'/'d' exponents
s_valsd = s_valsd.lower()
- s_valsd = s_valsd.replace('d','e')
- if 'e' in s_valsd:
- s_mantsd, s_exp = s_valsd.split('e')
+ s_valsd = s_valsd.replace("d", "e")
+ if "e" in s_valsd:
+ s_mantsd, s_exp = s_valsd.split("e")
exp = int(s_exp)
else:
s_mantsd = s_valsd
exp = 0
- patt = r'([+-]?\d*\.?\d*)\(?(\d+)?\)?'
+ patt = r"([+-]?\d*\.?\d*)\(?(\d+)?\)?"
m = re.match(patt, s_mantsd)
if not m:
- raise QuantityError('Failed to parse string into quantity:\n'\
- '%s' % s_mantsd)
+ raise QuantityError(
+ "Failed to parse string into quantity:\n" "%s" % s_mantsd
+ )
s_mantissa, s_sd = m.groups()
mantissa = float(s_mantissa)
value = mantissa * 10**exp
sd = None
if s_sd:
- if '.' in s_mantissa:
- ndp = len(s_mantissa) - s_mantissa.index('.') - 1
+ if "." in s_mantissa:
+ ndp = len(s_mantissa) - s_mantissa.index(".") - 1
else:
ndp = 0
- sd = float(s_sd) * 10**(exp-ndp)
+ sd = float(s_sd) * 10 ** (exp - ndp)
return Quantity(name=name, value=value, units=units, sd=sd)
diff --git a/src/pyqn/si.py b/src/pyqn/si.py
index 16f8db2..b88ed93 100644
--- a/src/pyqn/si.py
+++ b/src/pyqn/si.py
@@ -1,4 +1,4 @@
- # si.py
+# si.py
# A class representing the SI prefixes (SIPrefix) and a list of the SI
# base units (si_unit_stems): length (L), mass (M), time (T), temperature
# (Theta), amount of substance (Q), current (C) and luminous intensity (I).
@@ -22,36 +22,39 @@
# You should have received a copy of the GNU General Public License
# along with PyQn. If not, see
+
class SIPrefix(object):
- """ A little class describing SI prefixes. """
+ """A little class describing SI prefixes."""
+
def __init__(self, prefix, name, power):
self.prefix = prefix
self.name = name
self.power = power
self.fac = 10**power
+
# Here are the SI prefixes that we recognise.
-si_prefixes = { 'y': SIPrefix('y', 'yocto', -24),
- 'z': SIPrefix('z', 'zepto', -21),
- 'a': SIPrefix('a', 'atto', -18),
- 'f': SIPrefix('f', 'femto', -15),
- 'p': SIPrefix('p', 'pico', -12),
- 'n': SIPrefix('n', 'nano', -9),
- 'μ': SIPrefix('μ', 'micro', -6),
- 'm': SIPrefix('m', 'milli', -3),
- 'c': SIPrefix('c', 'centi', -2),
- 'd': SIPrefix('d', 'deci', -1),
- 'k': SIPrefix('k', 'kilo', 3),
- 'M': SIPrefix('M', 'mega', 6),
- 'G': SIPrefix('G', 'giga', 9),
- 'T': SIPrefix('T', 'tera', 12),
- 'P': SIPrefix('P', 'peta', 15),
- 'E': SIPrefix('E', 'exa', 18),
- 'Z': SIPrefix('Z', 'zetta', 21),
- 'Y': SIPrefix('Y', 'yotta', 24),
- }
+si_prefixes = {
+ "y": SIPrefix("y", "yocto", -24),
+ "z": SIPrefix("z", "zepto", -21),
+ "a": SIPrefix("a", "atto", -18),
+ "f": SIPrefix("f", "femto", -15),
+ "p": SIPrefix("p", "pico", -12),
+ "n": SIPrefix("n", "nano", -9),
+ "μ": SIPrefix("μ", "micro", -6),
+ "m": SIPrefix("m", "milli", -3),
+ "c": SIPrefix("c", "centi", -2),
+ "d": SIPrefix("d", "deci", -1),
+ "k": SIPrefix("k", "kilo", 3),
+ "M": SIPrefix("M", "mega", 6),
+ "G": SIPrefix("G", "giga", 9),
+ "T": SIPrefix("T", "tera", 12),
+ "P": SIPrefix("P", "peta", 15),
+ "E": SIPrefix("E", "exa", 18),
+ "Z": SIPrefix("Z", "zetta", 21),
+ "Y": SIPrefix("Y", "yotta", 24),
+}
# The base SI unit stems for length, time, mass, amount of substance,
# thermodynamic temperature, luminous intenstiy and current respectively:
-si_unit_stems = ('m', 's', 'g', 'mol', 'K', 'cd', 'A')
-
+si_unit_stems = ("m", "s", "g", "mol", "K", "cd", "A")
diff --git a/src/pyqn/symbol.py b/src/pyqn/symbol.py
index 4b7115e..648d487 100644
--- a/src/pyqn/symbol.py
+++ b/src/pyqn/symbol.py
@@ -21,6 +21,7 @@
# You should have received a copy of the GNU General Public License
# along with PyQn. If not, see
+
class Symbol(object):
"""
A Python class representing a symbol - typically the label for a physical
diff --git a/src/pyqn/units.py b/src/pyqn/units.py
index 4228dcc..bb094c6 100644
--- a/src/pyqn/units.py
+++ b/src/pyqn/units.py
@@ -22,13 +22,13 @@
import copy
from .dimensions import Dimensions
-from .dimensions import (d_dimensionless, d_length, d_energy, d_time,
- d_temperature)
+from .dimensions import d_dimensionless, d_length, d_energy, d_time, d_temperature
from .atom_unit import AtomUnit, UnitsError, feq
-h, NA, c, kB = (6.62607015e-34, 6.02214076e+23, 299792458.0, 1.380649e-23)
+h, NA, c, kB = (6.62607015e-34, 6.02214076e23, 299792458.0, 1.380649e-23)
-class Units(object):
+
+class Units:
"""
A class to represent the units of a physical quantity.
@@ -41,15 +41,26 @@ def __init__(self, units):
"""
+ self.undef = False
+ self.dims = None
+
if type(units) is Units:
+ if units.undef:
+ self.undef = True
+ return
self.__init__(units.atom_units)
elif type(units) is str:
+ if units == "undef":
+ self.undef = True
+ return
self.__init__(self.parse(units).atom_units)
elif type(units) is list:
self.atom_units = copy.deepcopy(units)
else:
- raise TypeError('Attempt to initialize Units object with'
- ' argument units of type %s' % type(units))
+ raise TypeError(
+ "Attempt to initialize Units object with"
+ " argument units of type %s" % type(units)
+ )
# also get the dimensions of the units
self.dims = self.get_dims()
@@ -78,7 +89,7 @@ def parse(self, s_compoundunit):
"""
- div_fields = s_compoundunit.split('/')
+ div_fields = s_compoundunit.split("/")
ndiv_fields = len(div_fields)
compound_unit = Units.parse_mult_units(div_fields[0])
for div_field in div_fields[1:]:
@@ -93,9 +104,9 @@ def parse_mult_units(self, munit):
"""
atom_units = []
- for s_unit in munit.split('.'):
+ for s_unit in munit.split("."):
atom_unit = AtomUnit.parse(s_unit)
- if atom_unit.base_unit.stem != '1':
+ if atom_unit.base_unit.stem != "1":
# the unity 'unit' is not really a unit
atom_units.append(atom_unit)
return Units(atom_units)
@@ -107,13 +118,13 @@ def _find_atom(self, atom_unit):
"""
- for i,my_atom_unit in enumerate(self.atom_units):
+ for i, my_atom_unit in enumerate(self.atom_units):
if my_atom_unit.prefix_base_eq(atom_unit):
return i
return None
def __mul__(self, other):
- """ Return the product of this Units object with another. """
+ """Return the product of this Units object with another."""
if other == 1:
return copy.deepcopy(self)
@@ -137,19 +148,20 @@ def __mul__(self, other):
del product.atom_units[i]
product.dims = product.get_dims()
return product
+
def __rmul__(self, other):
if type(other) == str:
other = Units(other)
elif other == 1:
- other = Units('1')
+ other = Units("1")
return self.__mul__(other)
def __truediv__(self, other):
- """ Return the ratio of this Units divided by another. """
+ """Return the ratio of this Units divided by another."""
if type(other) == str:
other = Units(other)
elif other == 1:
- other = Units('1')
+ other = Units("1")
ratio = Units(self.atom_units)
for other_atom_unit in other.atom_units:
i = ratio._find_atom(other_atom_unit)
@@ -166,37 +178,48 @@ def __truediv__(self, other):
del ratio.atom_units[i]
ratio.dims = ratio.get_dims()
return ratio
-
+
def __rdiv__(self, other):
if type(other) == str:
other = Units(other)
elif other == 1:
- other = Units('1')
+ other = Units("1")
return other.__truediv__(self)
-
+
def __pow__(self, power):
result_atom_units = []
for atom_unit in self.atom_units:
result_atom_units.append(atom_unit**power)
return Units(result_atom_units)
-
- def __str__(self):
- """ String representation of this Units. """
- return '.'.join([str(atom_unit) for atom_unit in self.atom_units])
- __repr__ = __str__
+ def __repr__(self):
+ """String representation of this Units."""
+ if self.undef:
+ return "undef"
+ return ".".join([str(atom_unit) for atom_unit in self.atom_units])
+
+ __str__ = __repr__
def __eq__(self, other):
- """ Test for equality with another Units object. """
+ """Test for equality with another Units object."""
+
if other is None:
return False
- elif other == 1:
+
+ if self.undef:
+ return False
+
+ if other == 1:
return self.get_dims() == d_dimensionless
+
+ if other.undef:
+ return False
+
if self.get_dims() != other.get_dims():
- # obviously the units aren't the same if they have different dimensions
+ # obviously the units aren't the same if they have different dimensions
return False
# if two Units objects have the same dimensions, they are equal if
- # their conversion factors to SI units are the same:
+ # their conversion factors to SI units are the same:
if feq(self.to_si(), other.to_si()):
return True
return False
@@ -205,38 +228,42 @@ def __ne__(self, other):
return not self == other
def to_si(self):
- """ Return the factor needed to convert this Units to SI. """
- fac = 1.
+ """Return the factor needed to convert this Units to SI."""
+ fac = 1.0
for atom_unit in self.atom_units:
fac *= atom_unit.si_fac
return fac
@property
def html(self):
+ if self.undef:
+ return "undef"
+
h = []
n = len(self.atom_units)
- for i,atom_unit in enumerate(self.atom_units):
- h.extend([atom_unit.prefix or '', atom_unit.base_unit.stem])
+ for i, atom_unit in enumerate(self.atom_units):
+ h.extend([atom_unit.prefix or "", atom_unit.base_unit.stem])
if atom_unit.exponent != 1:
- h.append('{:d}'.format(atom_unit.exponent))
- if i < n-1:
- h.append(' ')
- return ''.join(h)
-
+ h.append("{:d}".format(atom_unit.exponent))
+ if i < n - 1:
+ h.append(" ")
+ return "".join(h)
@property
def latex(self):
+ if self.undef:
+ return r"\mathrm{undef}"
+
e = []
n = len(self.atom_units)
for i, atom_unit in enumerate(self.atom_units):
# TODO use proper LaTeX for prefix.
- e.extend([atom_unit.prefix or '', atom_unit.base_unit.latex])
+ e.extend([atom_unit.prefix or "", atom_unit.base_unit.latex])
if atom_unit.exponent != 1:
- e.append('^{' + str(atom_unit.exponent) + '}')
- if i < n-1:
- e.append(r'\,')
- return r'\mathrm{' + ''.join(e) + '}'
-
+ e.append("^{" + str(atom_unit.exponent) + "}")
+ if i < n - 1:
+ e.append(r"\,")
+ return r"\mathrm{" + "".join(e) + "}"
def conversion(self, other, force=None, strict=False):
"""
@@ -246,82 +273,93 @@ def conversion(self, other, force=None, strict=False):
force='spec': spectroscopic units: conversions between [L-1],
[M,L2,T-2], [T-1] are allowed (i.e. cm-1, s-1, and J can be
interconverted through factors of h, hc).
-
+
"""
if type(other) == str:
other = Units(other)
-
+
conversion_method = {
- 'spec': self.spec_conversion,
- 'mol': self.mol_conversion,
- 'kBT': self.kBT_conversion
- }
+ "spec": self.spec_conversion,
+ "mol": self.mol_conversion,
+ "kBT": self.kBT_conversion,
+ }
self_dims, other_dims = self.get_dims(), other.get_dims()
if self_dims != other_dims:
try:
return conversion_method[force](other)
except KeyError:
- raise UnitsError('Failure in units conversion: units %s[%s] and'
- ' %s[%s] have different dimensions'
- % (self, self.get_dims(), other, other.get_dims()))
+ raise UnitsError(
+ "Failure in units conversion: units %s[%s] and"
+ " %s[%s] have different dimensions"
+ % (self, self.get_dims(), other, other.get_dims())
+ )
return self.to_si() / other.to_si()
-
+
def kBT_conversion(self, other):
from_dims = self.get_dims()
to_dims = other.get_dims()
fac = self.to_si()
-
+
if from_dims == d_energy and to_dims == d_temperature:
fac = fac / kB
elif from_dims == d_temperature and to_dims == d_energy:
fac = fac * kB
else:
- raise UnitsError('Failure in conversion of units: was expecting to '
- 'covert between energy and temperature')
- return fac/other.to_si()
+ raise UnitsError(
+ "Failure in conversion of units: was expecting to "
+ "covert between energy and temperature"
+ )
+ return fac / other.to_si()
def mol_conversion(self, other):
- from_dims = self.get_dims() #original unit dimensions
- to_dims = other.get_dims() #desired unit dimensions
- fac = self.to_si() #factor needed to conver to SI units
-
+ from_dims = self.get_dims() # original unit dimensions
+ to_dims = other.get_dims() # desired unit dimensions
+ fac = self.to_si() # factor needed to conver to SI units
+
if from_dims.dims[4] == to_dims.dims[4]:
- raise UnitsError('Failure in conversion of units: no '
- 'different in quantity dimensions between %s and %s'
- % from_dims, to_dims)
+ raise UnitsError(
+ "Failure in conversion of units: no "
+ "different in quantity dimensions between %s and %s" % from_dims,
+ to_dims,
+ )
elif from_dims.dims[4] > to_dims.dims[4]:
- fac = fac/(NA**(from_dims.dims[4]-to_dims.dims[4]))
+ fac = fac / (NA ** (from_dims.dims[4] - to_dims.dims[4]))
else:
- fac = fac*(NA**(to_dims.dims[4]-from_dims.dims[4]))
- return fac/other.to_si()
-
+ fac = fac * (NA ** (to_dims.dims[4] - from_dims.dims[4]))
+ return fac / other.to_si()
+
def spec_conversion(self, other):
d_wavenumber = d_length**-1
d_frequency = d_time**-1
d_wavelength = d_length
-
+
from_dims = self.get_dims()
to_dims = other.get_dims()
fac = self.to_si()
if from_dims == d_wavenumber:
- fac *= h*c
+ fac *= h * c
elif from_dims == d_frequency:
fac *= h
elif from_dims != d_energy:
- raise UnitsError('Failure in conversion of spectroscopic units:'
- ' I only recognise from-units of wavenumber, energy and'
- ' frequency but got %s' % str(self))
+ raise UnitsError(
+ "Failure in conversion of spectroscopic units:"
+ " I only recognise from-units of wavenumber, energy and"
+ " frequency but got %s" % str(self)
+ )
if to_dims == d_wavenumber:
- fac /= h*c
+ fac /= h * c
elif to_dims == d_frequency:
fac /= h
elif to_dims != d_energy:
- raise UnitsError('Failure in conversion of spectroscopic units:'
- ' I only recognise to-units of wavenumber, energy and'
- ' frequency but got %s' % str(other))
+ raise UnitsError(
+ "Failure in conversion of spectroscopic units:"
+ " I only recognise to-units of wavenumber, energy and"
+ " frequency but got %s" % str(other)
+ )
return fac / other.to_si()
+
def convert(from_units, to_units):
return Units(from_units).conversion(to_units)
diff --git a/tests/test_conversions.py b/tests/test_conversions.py
index 2c91aa0..56b7179 100644
--- a/tests/test_conversions.py
+++ b/tests/test_conversions.py
@@ -8,14 +8,15 @@
import unittest
from pyqn.units import Units, UnitsError
+
class UnitsConversionCheck(unittest.TestCase):
"""Unit tests for unit conversions within the Units class."""
def test_regular_units_conversion(self):
- u1 = Units('m.s-1')
- u2 = Units('cm.s-1')
- u3 = Units('ft.hr-1')
- u4 = Units('m.s-2')
+ u1 = Units("m.s-1")
+ u2 = Units("cm.s-1")
+ u3 = Units("ft.hr-1")
+ u4 = Units("m.s-2")
self.assertAlmostEqual(u1.conversion(u2), 100)
self.assertAlmostEqual(u2.conversion(u1), 0.01)
@@ -24,35 +25,33 @@ def test_regular_units_conversion(self):
u1.conversion(u4)
def test_litres(self):
- u1 = Units('l')
- self.assertEqual(u1.to_si(), 1.e-3)
- u2 = Units('L')
- self.assertEqual(u1.to_si(), 1.e-3)
+ u1 = Units("l")
+ self.assertEqual(u1.to_si(), 1.0e-3)
+ u2 = Units("L")
+ self.assertEqual(u1.to_si(), 1.0e-3)
def test_molar_units_conversion(self):
- u1 = Units('kJ')
- u2 = Units('J/mol')
+ u1 = Units("kJ")
+ u2 = Units("J/mol")
with self.assertRaises(UnitsError) as cm:
u1.conversion(u2, strict=True)
- self.assertAlmostEqual(u1.conversion(u2, force='mol'), 1.660e-21)
-
+ self.assertAlmostEqual(u1.conversion(u2, force="mol"), 1.660e-21)
+
def test_kBT_units_conversion(self):
- u1 = Units('K')
- u2 = Units('J')
-
- self.assertAlmostEqual(u1.conversion(u2, force='kBT'), 1.38064852e-23)
-
+ u1 = Units("K")
+ u2 = Units("J")
+
+ self.assertAlmostEqual(u1.conversion(u2, force="kBT"), 1.38064852e-23)
+
def test_spec_conversions(self):
- u1 = Units('J')
- u2 = Units('cm-1')
- u3 = Units('s-1')
-
- self.assertAlmostEqual(u1.conversion(u2, force='spec'),
- 5.0341165675427096e+22)
- self.assertAlmostEqual(u1.conversion(u3, force='spec'),
- 1.5091901796421518e+33)
-
-if __name__ == '__main__':
- unittest.main()
+ u1 = Units("J")
+ u2 = Units("cm-1")
+ u3 = Units("s-1")
+
+ self.assertAlmostEqual(u1.conversion(u2, force="spec"), 5.0341165675427096e22)
+ self.assertAlmostEqual(u1.conversion(u3, force="spec"), 1.5091901796421518e33)
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_quantity.py b/tests/test_quantity.py
index f1864f9..ce84778 100644
--- a/tests/test_quantity.py
+++ b/tests/test_quantity.py
@@ -3,78 +3,79 @@
from pyqn.dimensions import Dimensions, d_energy
from pyqn.units import UnitsError
+
class QuantityManipulations(unittest.TestCase):
def test_quantity_init(self):
pass
-
+
def test_quantity_multiplication(self):
- q1 = Quantity(value=22.4,units='m/s')
- q2 = Quantity(value=2,units='s')
-
- q3 = q1*q2
- self.assertAlmostEqual(q3.value,44.8)
- self.assertEqual(q3.units.dims.dims,(1,0,0,0,0,0,0))
-
+ q1 = Quantity(value=22.4, units="m/s")
+ q2 = Quantity(value=2, units="s")
+
+ q3 = q1 * q2
+ self.assertAlmostEqual(q3.value, 44.8)
+ self.assertEqual(q3.units.dims.dims, (1, 0, 0, 0, 0, 0, 0))
+
def test_quantity_division(self):
- q1 = Quantity(value=39, units='J')
- q2 = Quantity(value=5, units='s')
- q4 = Quantity(value=0, units='m')
-
- q3 = q1/q2
- self.assertAlmostEqual(q3.value,7.8)
- self.assertEqual(q3.units.dims,Dimensions(M=1,L=2,T=-3))
- q3 = q2/q1
- self.assertAlmostEqual(q3.value,0.128205128205)
- self.assertEqual(q3.units.dims,Dimensions(M=-1,L=-2,T=3))
-
+ q1 = Quantity(value=39, units="J")
+ q2 = Quantity(value=5, units="s")
+ q4 = Quantity(value=0, units="m")
+
+ q3 = q1 / q2
+ self.assertAlmostEqual(q3.value, 7.8)
+ self.assertEqual(q3.units.dims, Dimensions(M=1, L=2, T=-3))
+ q3 = q2 / q1
+ self.assertAlmostEqual(q3.value, 0.128205128205)
+ self.assertEqual(q3.units.dims, Dimensions(M=-1, L=-2, T=3))
+
with self.assertRaises(ZeroDivisionError) as cm:
- q3 = q1/q4
-
-
+ q3 = q1 / q4
+
def test_quantity_addition(self):
- q1 = Quantity(value = 20.5, units = 'J')
- q2 = Quantity(value = 30.7, units = 'kg.m2.s-2')
- q3 = Quantity(value = 5.1, units = 'K')
-
- q4 = q1+q2
- self.assertEqual(q4.value,51.2)
- self.assertEqual(q4.units.dims,Dimensions(M=1,L=2,T=-2))
-
+ q1 = Quantity(value=20.5, units="J")
+ q2 = Quantity(value=30.7, units="kg.m2.s-2")
+ q3 = Quantity(value=5.1, units="K")
+
+ q4 = q1 + q2
+ self.assertEqual(q4.value, 51.2)
+ self.assertEqual(q4.units.dims, Dimensions(M=1, L=2, T=-2))
+
with self.assertRaises(UnitsError) as cm:
q4 = q1 + q3
-
+
def test_quantity_subtraction(self):
- q1 = Quantity(value = 20.5, units = 'J')
- q2 = Quantity(value = 30.7, units = 'kg.m2.s-2')
- q3 = Quantity(value = 5.1, units = 'K')
-
- q4 = q1-q2
- self.assertEqual(q4.value,-10.2)
- self.assertEqual(q4.units.dims,Dimensions(M=1,L=2,T=-2))
-
+ q1 = Quantity(value=20.5, units="J")
+ q2 = Quantity(value=30.7, units="kg.m2.s-2")
+ q3 = Quantity(value=5.1, units="K")
+
+ q4 = q1 - q2
+ self.assertEqual(q4.value, -10.2)
+ self.assertEqual(q4.units.dims, Dimensions(M=1, L=2, T=-2))
+
with self.assertRaises(UnitsError) as cm:
q4 = q1 - q3
-
+
def test_quantity_exponent(self):
- q1 = Quantity(value = 1.2, units = 'J')
- q2 = Quantity(value = -5, units = 's')
-
+ q1 = Quantity(value=1.2, units="J")
+ q2 = Quantity(value=-5, units="s")
+
q3 = q1**4
q4 = q2**-1
- self.assertEqual(q3.value,2.0736)
- self.assertEqual(q3.units.dims,Dimensions(M=4,L=8,T=-8))
+ self.assertEqual(q3.value, 2.0736)
+ self.assertEqual(q3.units.dims, Dimensions(M=4, L=8, T=-8))
self.assertEqual(q4.value, -0.2)
- self.assertEqual(q4.units.dims,Dimensions(T=-1))
-
+ self.assertEqual(q4.units.dims, Dimensions(T=-1))
+
q5 = q1**0
- self.assertEqual(q5.value,1)
- self.assertNotEqual(q1.units.dims,q5.units.dims)
-
+ self.assertEqual(q5.value, 1)
+ self.assertNotEqual(q1.units.dims, q5.units.dims)
+
def test_quantity_conversion(self):
- #q1 = Quantity(value = 200, units = 'J')
- #q2 = q1.convert_units_to('eV')
- #self.assertAlmostEqual(q2.value,1.2483019242e+21,places=2)
+ # q1 = Quantity(value = 200, units = 'J')
+ # q2 = q1.convert_units_to('eV')
+ # self.assertAlmostEqual(q2.value,1.2483019242e+21,places=2)
pass
-
-if __name__ == '__main__':
+
+
+if __name__ == "__main__":
unittest.main()
diff --git a/tests/test_undef.py b/tests/test_undef.py
new file mode 100644
index 0000000..bf01d33
--- /dev/null
+++ b/tests/test_undef.py
@@ -0,0 +1,18 @@
+import unittest
+from pyqn.units import Units
+
+
+class TestUndef(unittest.TestCase):
+ def test_undef(self):
+ u1 = Units("undef")
+ self.assertTrue(u1.undef)
+ self.assertEqual(repr(u1), "undef")
+ self.assertEqual(u1.html, "undef")
+
+ u2 = Units("cm.hr-1/m")
+
+ for u3 in (Units("undef"), 1, None):
+ self.assertFalse(u1 == u3)
+ self.assertTrue(u1 != u3)
+ self.assertFalse(u2 == u3)
+ self.assertTrue(u2 != u3)
diff --git a/tests/test_units.py b/tests/test_units.py
index 1e80d35..b9bab05 100644
--- a/tests/test_units.py
+++ b/tests/test_units.py
@@ -7,104 +7,106 @@
import unittest
from pyqn.units import Units
-from pyqn.dimensions import Dimensions,d_energy
+from pyqn.dimensions import Dimensions, d_energy
+
class UnitsCheck(unittest.TestCase):
"""Unit tests for the Units class."""
def test_units_algebra(self):
- u1 = Units('m.s-1')
+ u1 = Units("m.s-1")
self.assertTrue(u1.has_units())
- u2 = Units('cm.hr-1/m')
+ u2 = Units("cm.hr-1/m")
- self.assertEqual(str(u1), 'm.s-1')
- self.assertEqual(str(u2), 'cm.hr-1.m-1')
+ self.assertEqual(str(u1), "m.s-1")
+ self.assertEqual(str(u2), "cm.hr-1.m-1")
- self.assertEqual(u1*u2, Units('cm.s-1.hr-1'))
- self.assertEqual(u1/u2, Units('m2.s-1.cm-1.hr'))
- self.assertEqual(u2/u1, Units('cm.hr-1.s/m2'))
+ self.assertEqual(u1 * u2, Units("cm.s-1.hr-1"))
+ self.assertEqual(u1 / u2, Units("m2.s-1.cm-1.hr"))
+ self.assertEqual(u2 / u1, Units("cm.hr-1.s/m2"))
- u3 = Units('J.A-1')
- u4 = Units('J.A-1')
+ u3 = Units("J.A-1")
+ u4 = Units("J.A-1")
u3_over_u4 = u3 / u4
self.assertFalse(u3_over_u4.has_units())
def test_units_multiplication(self):
- u1 = Units('m.s-1')
+ u1 = Units("m.s-1")
u2 = u1 * 1
-
+
self.assertEqual(u2, u1)
- self.assertNotEqual(id(u1), id(u2))
-
+ self.assertNotEqual(id(u1), id(u2))
+
u2 = 1 * u1
self.assertEqual(u2, u1)
- self.assertNotEqual(id(u1), id(u2))
-
- u1 = Units('m.s-1')
- u2 = Units('J')
- self.assertEqual('kg.m.s-1' * u1, u2)
-
- u1 = Units('m.s-1')
- u2 = Units('J')
- self.assertEqual(u1 * 'kg.m.s-1', u2)
-
- u1 = Units('mm2')
- u2 = Units('g/m2')
+ self.assertNotEqual(id(u1), id(u2))
+
+ u1 = Units("m.s-1")
+ u2 = Units("J")
+ self.assertEqual("kg.m.s-1" * u1, u2)
+
+ u1 = Units("m.s-1")
+ u2 = Units("J")
+ self.assertEqual(u1 * "kg.m.s-1", u2)
+
+ u1 = Units("mm2")
+ u2 = Units("g/m2")
u3 = u1 * u2
- self.assertAlmostEqual(u3.to_si(), 1.e-9)
- self.assertTupleEqual(u3.get_dims().dims,(0, 1, 0, 0, 0, 0, 0))
-
- u4 = Units('J/s')
+ self.assertAlmostEqual(u3.to_si(), 1.0e-9)
+ self.assertTupleEqual(u3.get_dims().dims, (0, 1, 0, 0, 0, 0, 0))
+
+ u4 = Units("J/s")
u5 = u4 * u2
- self.assertAlmostEqual(u5.to_si(), 1.e-3)
- self.assertEqual(u5.get_dims().dims,(0,2,-3,0,0,0,0))
+ self.assertAlmostEqual(u5.to_si(), 1.0e-3)
+ self.assertEqual(u5.get_dims().dims, (0, 2, -3, 0, 0, 0, 0))
def test_units_division(self):
- u1 = Units('eV.mm')
- u2 = Units('K.cm')
-
+ u1 = Units("eV.mm")
+ u2 = Units("K.cm")
+
u3 = u1 / u2
- self.assertEqual(u3.get_dims().dims,(2,1,-2,-1,0,0,0))
- self.assertAlmostEqual(u3.to_si(),1.6*10**(-20))
-
- u4 = Units('s-1')
- u5 = u2 / ('eV'*u4)
- self.assertEqual(u5.get_dims(),Dimensions(T=1,Theta=1,L=1)/d_energy)
-
+ self.assertEqual(u3.get_dims().dims, (2, 1, -2, -1, 0, 0, 0))
+ self.assertAlmostEqual(u3.to_si(), 1.6 * 10 ** (-20))
+
+ u4 = Units("s-1")
+ u5 = u2 / ("eV" * u4)
+ self.assertEqual(u5.get_dims(), Dimensions(T=1, Theta=1, L=1) / d_energy)
+
def test_units_power(self):
- u1 = Units('J.m')
- u2 = u1 ** 2
- self.assertEqual(u2.get_dims(),Dimensions(M=2,L=6,T=-4))
-
+ u1 = Units("J.m")
+ u2 = u1**2
+ self.assertEqual(u2.get_dims(), Dimensions(M=2, L=6, T=-4))
+
u3 = u1 ** (-1)
- self.assertEqual(u3.get_dims(),Dimensions(M=-1,L=-3,T=2))
-
+ self.assertEqual(u3.get_dims(), Dimensions(M=-1, L=-3, T=2))
+
u4 = u1 ** (-2)
- self.assertEqual(u4.get_dims(),Dimensions(M=-2,L=-6,T=4))
-
- u5 = u1 ** 0
- self.assertEqual(u5.get_dims(),Dimensions())
-
+ self.assertEqual(u4.get_dims(), Dimensions(M=-2, L=-6, T=4))
+
+ u5 = u1**0
+ self.assertEqual(u5.get_dims(), Dimensions())
+
def test_units_algebra_dimensions(self):
- u1 = Units('m')
- u2 = Units('m.s-1')
+ u1 = Units("m")
+ u2 = Units("m.s-1")
u3 = u1 * u2
- u4 = Units('m2.s-1')
+ u4 = Units("m2.s-1")
self.assertEqual(u3.dims, u4.dims)
u3 = u1 / u2
- u4 = Units('s')
+ u4 = Units("s")
self.assertEqual(u3.dims, u4.dims)
def test_unicode_units(self):
- u1 = Units('kΩ')
- self.assertEqual(str(u1), 'kΩ')
+ u1 = Units("kΩ")
+ self.assertEqual(str(u1), "kΩ")
def test_html(self):
- u1 = Units('m.s-1')
- self.assertEqual(u1.html, 'm s-1')
- u2 = Units('μs.J/m3')
- self.assertEqual(u2.html, 'μs J m-3')
+ u1 = Units("m.s-1")
+ self.assertEqual(u1.html, "m s-1")
+ u2 = Units("μs.J/m3")
+ self.assertEqual(u2.html, "μs J m-3")
+
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/tests/test_units_collisions.py b/tests/test_units_collisions.py
index f198d86..e9e5930 100644
--- a/tests/test_units_collisions.py
+++ b/tests/test_units_collisions.py
@@ -12,6 +12,7 @@
from pyqn.base_unit import base_units
from pyqn.si import si_prefixes
+
class ConflictsCheck(unittest.TestCase):
"""
Check that there are no conflicts amongst the allowed derived and
@@ -20,15 +21,20 @@ class ConflictsCheck(unittest.TestCase):
"""
def test_units_conflicts(self):
- prefixes = ['']; prefixes.extend(si_prefixes)
+ prefixes = [""]
+ prefixes.extend(si_prefixes)
seen_units = []
for base_unit_group in base_units:
for base_unit in base_unit_group[1]:
for si_prefix in prefixes:
- this_unit = '%s%s' % (si_prefix, base_unit.stem)
- self.assertEqual(this_unit in seen_units, False,
- 'Clash with unit: %s' % this_unit)
+ this_unit = "%s%s" % (si_prefix, base_unit.stem)
+ self.assertEqual(
+ this_unit in seen_units,
+ False,
+ "Clash with unit: %s" % this_unit,
+ )
seen_units.append(this_unit)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()