Commit 0b4a1077 authored by peastman's avatar peastman
Browse files

Merge pull request #972 from swails/unit

A large number of unit cleanups and fix numpy wart
parents 83d092af d05b7075
...@@ -2712,10 +2712,6 @@ multiply operator (‘*’) or the explicit Quantity constructor: ...@@ -2712,10 +2712,6 @@ multiply operator (‘*’) or the explicit Quantity constructor:
# or more verbosely # or more verbosely
bond_length = Quantity(value=1.53, unit=nanometer) bond_length = Quantity(value=1.53, unit=nanometer)
When working with Numpy arrays you *must* use the explicit constructor. You cannot
multiply them by a unit, because the Numpy array class overloads the multiply operator.
Arithmetic with units Arithmetic with units
--------------------- ---------------------
...@@ -2865,7 +2861,7 @@ in and out. ...@@ -2865,7 +2861,7 @@ in and out.
[[10.0, 20.0, 30.0], [40.0, 50.0, 60.0]] [[10.0, 20.0, 30.0], [40.0, 50.0, 60.0]]
>>> import numpy >>> import numpy
>>> a = Quantity(numpy.array([1,2,3]), centimeter) >>> a = numpy.array([1,2,3]) * centimeter
>>> print(a) >>> print(a)
[1 2 3] cm [1 2 3] cm
>>> print(a/millimeter) >>> print(a/millimeter)
......
#!/bin/env python #!/bin/env python
""" """
Module simtk.unit.basedimension Module simtk.unit.basedimension
...@@ -34,6 +32,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -34,6 +32,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import print_function, division
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.6" __version__ = "0.6"
......
...@@ -33,6 +33,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -33,6 +33,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import print_function, division, absolute_import
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.6" __version__ = "0.6"
...@@ -44,6 +45,7 @@ class BaseUnit(object): ...@@ -44,6 +45,7 @@ class BaseUnit(object):
For example, meter_base_unit could be a BaseUnit for the length dimension. For example, meter_base_unit could be a BaseUnit for the length dimension.
The BaseUnit class is used internally in the more general Unit class. The BaseUnit class is used internally in the more general Unit class.
''' '''
__array_priority__ = 100
def __init__(self, base_dim, name, symbol): def __init__(self, base_dim, name, symbol):
"""Creates a new BaseUnit. """Creates a new BaseUnit.
...@@ -127,7 +129,7 @@ class BaseUnit(object): ...@@ -127,7 +129,7 @@ class BaseUnit(object):
self._conversion_factor_to_by_name[other.name] = factor self._conversion_factor_to_by_name[other.name] = factor
for (unit, cfac) in other._conversion_factor_to.items(): for (unit, cfac) in other._conversion_factor_to.items():
if unit is self: continue if unit is self: continue
if self._conversion_factor_to.has_key(unit): continue if unit in self._conversion_factor_to: continue
self._conversion_factor_to[unit] = factor * cfac self._conversion_factor_to[unit] = factor * cfac
unit._conversion_factor_to[self] = pow(factor * cfac, -1) unit._conversion_factor_to[self] = pow(factor * cfac, -1)
self._conversion_factor_to_by_name[unit.name] = factor * cfac self._conversion_factor_to_by_name[unit.name] = factor * cfac
...@@ -138,7 +140,7 @@ class BaseUnit(object): ...@@ -138,7 +140,7 @@ class BaseUnit(object):
other._conversion_factor_to_by_name[self.name] = invFac other._conversion_factor_to_by_name[self.name] = invFac
for (unit, cfac) in self._conversion_factor_to.items(): for (unit, cfac) in self._conversion_factor_to.items():
if unit is other: continue if unit is other: continue
if other._conversion_factor_to.has_key(unit): continue if unit in other._conversion_factor_to: continue
other._conversion_factor_to[unit] = invFac * cfac other._conversion_factor_to[unit] = invFac * cfac
unit._conversion_factor_to[other] = pow(invFac * cfac, -1) unit._conversion_factor_to[other] = pow(invFac * cfac, -1)
other._conversion_factor_to_by_name[unit.name] = invFac * cfac other._conversion_factor_to_by_name[unit.name] = invFac * cfac
......
...@@ -29,13 +29,12 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -29,13 +29,12 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import print_function, division, absolute_import
from __future__ import division
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.5" __version__ = "0.5"
from unit_definitions import * from .unit_definitions import *
################# #################
### CONSTANTS ### ### CONSTANTS ###
......
...@@ -28,6 +28,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -28,6 +28,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import print_function, division, absolute_import
import sys import sys
...@@ -41,9 +42,9 @@ def eye(size): ...@@ -41,9 +42,9 @@ def eye(size):
[0, 0, 1]] [0, 0, 1]]
""" """
result = [] result = []
for row in range(0, size): for row in range(size):
r = [] r = []
for col in range(0, size): for col in range(size):
if row == col: if row == col:
r.append(1) r.append(1)
else: else:
...@@ -63,9 +64,9 @@ def zeros(m, n=None): ...@@ -63,9 +64,9 @@ def zeros(m, n=None):
if n is None: if n is None:
n = m n = m
result = [] result = []
for row in range(0, m): for row in range(m):
r = [] r = []
for col in range(0, n): for col in range(n):
r.append(0) r.append(0)
result.append(r) result.append(r)
return MyMatrix(result) return MyMatrix(result)
...@@ -171,7 +172,7 @@ class MyMatrix(MyVector): ...@@ -171,7 +172,7 @@ class MyMatrix(MyVector):
def __str__(self): def __str__(self):
result = "" result = ""
start_char = "[" start_char = "["
for m in range(0, self.numRows()): for m in range(self.numRows()):
result += start_char result += start_char
result += str(self[m]) result += str(self[m])
if m < self.numRows() - 1: if m < self.numRows() - 1:
...@@ -226,9 +227,9 @@ class MyMatrix(MyVector): ...@@ -226,9 +227,9 @@ class MyMatrix(MyVector):
if self.numCols() != r: if self.numCols() != r:
raise ArithmeticError("Matrix multplication size mismatch (%d vs %d)" % (self.numCols(), r)) raise ArithmeticError("Matrix multplication size mismatch (%d vs %d)" % (self.numCols(), r))
result = zeros(m, n) result = zeros(m, n)
for i in range(0, m): for i in range(m):
for j in range(0, n): for j in range(n):
for k in range(0, r): for k in range(r):
result[i][j] += self[i][k]*rhs[k][j] result[i][j] += self[i][k]*rhs[k][j]
return result return result
...@@ -245,8 +246,8 @@ class MyMatrix(MyVector): ...@@ -245,8 +246,8 @@ class MyMatrix(MyVector):
assert len(rhs) == m assert len(rhs) == m
assert len(rhs[0]) == n assert len(rhs[0]) == n
result = zeros(m,n) result = zeros(m,n)
for i in range(0,m): for i in range(m):
for j in range(0,n): for j in range(n):
result[i][j] = self[i][j] + rhs[i][j] result[i][j] = self[i][j] + rhs[i][j]
return result return result
...@@ -263,8 +264,8 @@ class MyMatrix(MyVector): ...@@ -263,8 +264,8 @@ class MyMatrix(MyVector):
assert len(rhs) == m assert len(rhs) == m
assert len(rhs[0]) == n assert len(rhs[0]) == n
result = zeros(m,n) result = zeros(m,n)
for i in range(0,m): for i in range(m):
for j in range(0,n): for j in range(n):
result[i][j] = self[i][j] - rhs[i][j] result[i][j] = self[i][j] - rhs[i][j]
return result return result
...@@ -275,8 +276,8 @@ class MyMatrix(MyVector): ...@@ -275,8 +276,8 @@ class MyMatrix(MyVector):
m = self.numRows() m = self.numRows()
n = self.numCols() n = self.numCols()
result = zeros(m, n) result = zeros(m, n)
for i in range(0,m): for i in range(m):
for j in range(0,n): for j in range(n):
result[i][j] = -self[i][j] result[i][j] = -self[i][j]
return result return result
...@@ -358,7 +359,7 @@ class MyMatrix(MyVector): ...@@ -358,7 +359,7 @@ class MyMatrix(MyVector):
ipiv[icol] += 1 ipiv[icol] += 1
# We now have the pivot element, so we interchange rows... # We now have the pivot element, so we interchange rows...
if irow != icol: if irow != icol:
for l in range(0,n): for l in range(n):
temp = a[irow][l] temp = a[irow][l]
a[irow][l] = a[icol][l] a[irow][l] = a[icol][l]
a[icol][l] = temp a[icol][l] = temp
...@@ -368,20 +369,20 @@ class MyMatrix(MyVector): ...@@ -368,20 +369,20 @@ class MyMatrix(MyVector):
raise ArithmeticError("Cannot invert singular matrix") raise ArithmeticError("Cannot invert singular matrix")
pivinv = 1.0/a[icol][icol] pivinv = 1.0/a[icol][icol]
a[icol][icol] = 1.0 a[icol][icol] = 1.0
for l in range(0,n): for l in range(n):
a[icol][l] *= pivinv a[icol][l] *= pivinv
for ll in range(0,n): # next we reduce the rows for ll in range(n): # next we reduce the rows
if ll == icol: if ll == icol:
continue # except the pivot one, of course continue # except the pivot one, of course
dum = a[ll][icol] dum = a[ll][icol]
a[ll][icol] = 0.0 a[ll][icol] = 0.0
for l in range(0,n): for l in range(n):
a[ll][l] -= a[icol][l]*dum a[ll][l] -= a[icol][l]*dum
# Unscramble the permuted columns # Unscramble the permuted columns
for l in range(n-1, -1, -1): for l in range(n-1, -1, -1):
if indxr[l] == indxc[l]: if indxr[l] == indxc[l]:
continue continue
for k in range(0,n): for k in range(n):
temp = a[k][indxr[l]] temp = a[k][indxr[l]]
a[k][indxr[l]] = a[k][indxc[l]] a[k][indxr[l]] = a[k][indxc[l]]
a[k][indxc[l]] = temp a[k][indxc[l]] = temp
...@@ -415,7 +416,7 @@ class MyMatrixTranspose(MyMatrix): ...@@ -415,7 +416,7 @@ class MyMatrixTranspose(MyMatrix):
return MyVector(result) return MyVector(result)
def __setitem__(self, key, rhs): def __setitem__(self, key, rhs):
for n in range(0, len(self.data)): for n in range(len(self.data)):
self.data[n][key] = rhs[n] self.data[n][key] = rhs[n]
def __str__(self): def __str__(self):
...@@ -423,11 +424,11 @@ class MyMatrixTranspose(MyMatrix): ...@@ -423,11 +424,11 @@ class MyMatrixTranspose(MyMatrix):
return "[[]]" return "[[]]"
start_char = "[" start_char = "["
result = "" result = ""
for m in range(0, len(self.data[0])): for m in range(len(self.data[0])):
result += start_char result += start_char
result += "[" result += "["
sep_char = "" sep_char = ""
for n in range(0, len(self.data)): for n in range(len(self.data)):
result += sep_char result += sep_char
result += str(self.data[n][m]) result += str(self.data[n][m])
sep_char = ", " sep_char = ", "
...@@ -443,11 +444,11 @@ class MyMatrixTranspose(MyMatrix): ...@@ -443,11 +444,11 @@ class MyMatrixTranspose(MyMatrix):
return "MyMatrixTranspose([[]])" return "MyMatrixTranspose([[]])"
start_char = "[" start_char = "["
result = 'MyMatrixTranspose(' result = 'MyMatrixTranspose('
for m in range(0, len(self.data[0])): for m in range(len(self.data[0])):
result += start_char result += start_char
result += "[" result += "["
sep_char = "" sep_char = ""
for n in range(0, len(self.data)): for n in range(len(self.data)):
result += sep_char result += sep_char
result += repr(self.data[n][m]) result += repr(self.data[n][m])
sep_char = ", " sep_char = ", "
......
...@@ -29,12 +29,13 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -29,12 +29,13 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import print_function, division, absolute_import
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.6" __version__ = "0.6"
from baseunit import BaseUnit from .baseunit import BaseUnit
from unit import Unit, ScaledUnit from .unit import Unit, ScaledUnit
import sys import sys
################### ###################
......
...@@ -67,8 +67,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -67,8 +67,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import division, print_function, absolute_import
from __future__ import division
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.5" __version__ = "0.5"
...@@ -76,8 +75,8 @@ __version__ = "0.5" ...@@ -76,8 +75,8 @@ __version__ = "0.5"
import math import math
import copy import copy
from standard_dimensions import * from .standard_dimensions import *
from unit import Unit, is_unit, dimensionless from .unit import Unit, is_unit, dimensionless
class Quantity(object): class Quantity(object):
"""Physical quantity, such as 1.3 meters per second. """Physical quantity, such as 1.3 meters per second.
...@@ -92,18 +91,8 @@ class Quantity(object): ...@@ -92,18 +91,8 @@ class Quantity(object):
Note - unit conversions will cause tuples to be converted to lists Note - unit conversions will cause tuples to be converted to lists
4 - lists of tuples of numbers, lists of lists of ... etc. of numbers 4 - lists of tuples of numbers, lists of lists of ... etc. of numbers
5 - numpy.arrays 5 - numpy.arrays
Create numpy.arrays with units using the Quantity constructor, not the
multiply operator. e.g.
Quantity(numpy.array([1,2,3]), centimeters) # correct
*NOT*
numpy.array([1,2,3]) * centimeters # won't work
because numpy.arrays already overload the multiply operator for EVERYTHING.
""" """
__array_priority__ = 99
def __init__(self, value=None, unit=None): def __init__(self, value=None, unit=None):
""" """
...@@ -136,7 +125,7 @@ class Quantity(object): ...@@ -136,7 +125,7 @@ class Quantity(object):
if len(value) < 1: if len(value) < 1:
unit = dimensionless unit = dimensionless
else: else:
first_item = iter(value).next() first_item = next(iter(value))
# Avoid infinite recursion for string, because a one-character # Avoid infinite recursion for string, because a one-character
# string is its own first element # string is its own first element
try: try:
...@@ -613,6 +602,9 @@ class Quantity(object): ...@@ -613,6 +602,9 @@ class Quantity(object):
""" """
return bool(self._value) return bool(self._value)
def __bool__(self):
return self.__nonzero__()
def __complex__(self): def __complex__(self):
return Quantity(complex(self._value), self.unit) return Quantity(complex(self._value), self.unit)
def __float__(self): def __float__(self):
...@@ -713,7 +705,7 @@ class Quantity(object): ...@@ -713,7 +705,7 @@ class Quantity(object):
else: else:
for i in range(len(value)): for i in range(len(value)):
value[i] = factor*value[i] value[i] = factor*value[i]
except TypeError as ex: except TypeError:
if isinstance(value, tuple): if isinstance(value, tuple):
value = tuple([self._scale_sequence(x, factor, post_multiply) for x in value]) value = tuple([self._scale_sequence(x, factor, post_multiply) for x in value])
else: else:
......
...@@ -31,11 +31,12 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -31,11 +31,12 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import division, print_function, absolute_import
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.6" __version__ = "0.6"
from basedimension import BaseDimension from .basedimension import BaseDimension
################## ##################
### DIMENSIONS ### ### DIMENSIONS ###
......
...@@ -31,8 +31,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -31,8 +31,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import division, print_function, absolute_import
from __future__ import division
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.5" __version__ = "0.5"
...@@ -40,15 +39,18 @@ __version__ = "0.5" ...@@ -40,15 +39,18 @@ __version__ = "0.5"
import math import math
import sys import sys
from mymatrix import MyMatrix, zeros from .mymatrix import MyMatrix, zeros
from basedimension import BaseDimension from .basedimension import BaseDimension
from baseunit import BaseUnit from .baseunit import BaseUnit
from standard_dimensions import * from .standard_dimensions import *
class Unit(object): class Unit(object):
""" """
Physical unit such as meter or ampere. Physical unit such as meter or ampere.
""" """
__array_priority__ = 100
def __init__(self, base_or_scaled_units): def __init__(self, base_or_scaled_units):
"""Create a new Unit. """Create a new Unit.
...@@ -495,6 +497,8 @@ class ScaledUnit(object): ...@@ -495,6 +497,8 @@ class ScaledUnit(object):
ScaledUnit and BaseUnit are both used in the internals of Unit. They ScaledUnit and BaseUnit are both used in the internals of Unit. They
should only be used during the construction of Units. should only be used during the construction of Units.
""" """
__array_priority__ = 100
def __init__(self, factor, master, name, symbol): def __init__(self, factor, master, name, symbol):
self.factor = factor self.factor = factor
# Convert to one base_unit per dimension # Convert to one base_unit per dimension
...@@ -576,6 +580,14 @@ class ScaledUnit(object): ...@@ -576,6 +580,14 @@ class ScaledUnit(object):
+ ", symbol=" + repr(self.symbol) + ")" + ", symbol=" + repr(self.symbol) + ")"
class UnitSystem(object): class UnitSystem(object):
"""
A complete system of units defining the *base* unit in each dimension
Parameters
----------
units: ``list``
List of base units from which to construct the unit system
"""
def __init__(self, units): def __init__(self, units):
self.units = units self.units = units
self._unit_conversion_cache = {} self._unit_conversion_cache = {}
......
...@@ -30,16 +30,16 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE ...@@ -30,16 +30,16 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import division from __future__ import division, print_function, absolute_import
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.6" __version__ = "0.6"
from baseunit import BaseUnit from .baseunit import BaseUnit
from standard_dimensions import * from .standard_dimensions import *
from unit import Unit, ScaledUnit, UnitSystem, dimensionless from .unit import Unit, ScaledUnit, UnitSystem, dimensionless
from unit_operators import * ; # needed for manipulation of units from .unit_operators import * ; # needed for manipulation of units
from prefix import * from .prefix import *
import math import math
import sys import sys
...@@ -303,20 +303,20 @@ mmHg = Unit({mmHg_base_unit: 1.0}) ...@@ -303,20 +303,20 @@ mmHg = Unit({mmHg_base_unit: 1.0})
ampere_base_unit = ScaledUnit(1.0, coulomb/second, "ampere", "A") ampere_base_unit = ScaledUnit(1.0, coulomb/second, "ampere", "A")
si_unit_system = UnitSystem([\ si_unit_system = UnitSystem([
meter_base_unit,\ meter_base_unit,
kilogram_base_unit,\ kilogram_base_unit,
second_base_unit,\ second_base_unit,
ampere_base_unit, ampere_base_unit,
kelvin_base_unit, kelvin_base_unit,
mole_base_unit, mole_base_unit,
candela_base_unit, candela_base_unit,
radian_base_unit]) radian_base_unit])
cgs_unit_system = UnitSystem([\ cgs_unit_system = UnitSystem([
centimeter_base_unit,\ centimeter_base_unit,
gram_base_unit,\ gram_base_unit,
second_base_unit,\ second_base_unit,
ampere_base_unit, ampere_base_unit,
kelvin_base_unit, kelvin_base_unit,
mole_base_unit, mole_base_unit,
...@@ -324,10 +324,10 @@ cgs_unit_system = UnitSystem([\ ...@@ -324,10 +324,10 @@ cgs_unit_system = UnitSystem([\
dalton_base_unit = ScaledUnit(1.0, gram/mole, "dalton", "Da") dalton_base_unit = ScaledUnit(1.0, gram/mole, "dalton", "Da")
md_unit_system = UnitSystem([\ md_unit_system = UnitSystem([
nanometer_base_unit,\ nanometer_base_unit,
dalton_base_unit, dalton_base_unit,
picosecond_base_unit,\ picosecond_base_unit,
elementary_charge_base_unit, elementary_charge_base_unit,
kelvin_base_unit, kelvin_base_unit,
mole_base_unit, mole_base_unit,
......
...@@ -31,16 +31,15 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -31,16 +31,15 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import division, print_function, absolute_import
from __future__ import division
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.5" __version__ = "0.5"
import math import math
from quantity import is_quantity from .quantity import is_quantity
from unit_definitions import * from .unit_definitions import *
#################### ####################
### TRIGONOMETRY ### ### TRIGONOMETRY ###
......
...@@ -46,12 +46,13 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ...@@ -46,12 +46,13 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
""" """
from __future__ import print_function, absolute_import, division
__author__ = "Christopher M. Bruns" __author__ = "Christopher M. Bruns"
__version__ = "0.5" __version__ = "0.5"
from unit import Unit, is_unit from .unit import Unit, is_unit
from quantity import Quantity, is_quantity from .quantity import Quantity, is_quantity
# Attach methods of Unit class that return a Quantity to Unit class. # Attach methods of Unit class that return a Quantity to Unit class.
# I put them here to avoid circular dependence in imports. # I put them here to avoid circular dependence in imports.
......
...@@ -638,6 +638,7 @@ class TestUnits(QuantityTestCase): ...@@ -638,6 +638,7 @@ class TestUnits(QuantityTestCase):
self.assertEqual(str(u.meters*u.meters), 'meter**2') self.assertEqual(str(u.meters*u.meters), 'meter**2')
self.assertEqual(str(u.meter*u.meter), 'meter**2') self.assertEqual(str(u.meter*u.meter), 'meter**2')
@unittest.skipIf(np is None, 'Skipping numpy units tests')
class TestNumpyUnits(QuantityTestCase): class TestNumpyUnits(QuantityTestCase):
def testNumpyQuantity(self): def testNumpyQuantity(self):
...@@ -686,6 +687,14 @@ class TestNumpyUnits(QuantityTestCase): ...@@ -686,6 +687,14 @@ class TestNumpyUnits(QuantityTestCase):
b = a.reshape((5, 2)) b = a.reshape((5, 2))
self.assertTrue(u.is_quantity(b)) self.assertTrue(u.is_quantity(b))
if np is None: def testMultiplication(self):
# Support lack of numpy """ Tests that units override numpy.ndarray multiplication """
del TestNumpyUnits self.assertIsInstance(np.arange(10)*u.angstroms, u.Quantity)
# This only works with versions of numpy > 1.7 due to a bug in older
# versions. Since Travis-CI installs Python 1.6.1 from aptitude, and we
# don't want it to report test failures *every time*, just disable this
# particular test for the numpy versions known to be bad.
if np.version.version > '1.7':
x = np.array([1]) * u.liters
self.assertIsInstance(x, u.Quantity)
self.assertIsInstance(np.arange(10) * x, u.Quantity)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment