Commit 4941cc7d authored by Justin MacCallum's avatar Justin MacCallum
Browse files

Removed trailing whitespace

parent 3862202e
......@@ -15,7 +15,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......@@ -40,14 +40,14 @@ __version__ = "0.6"
class BaseUnit(object):
'''
Physical unit expressed in exactly one BaseDimension.
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.
'''
def __init__(self, base_dim, name, symbol):
"""Creates a new BaseUnit.
Parameters
- self: The newly created BaseUnit.
- base_dim: (BaseDimension) The dimension of the new unit, e.g. 'mass'
......@@ -62,7 +62,7 @@ class BaseUnit(object):
self._conversion_factor_to[self] = 1.0
self._conversion_factor_to_by_name = {}
self._conversion_factor_to_by_name[self.name] = 1.0
def __lt__(self, other):
"""
Comparison function that sorts BaseUnits by BaseDimension
......@@ -78,10 +78,10 @@ class BaseUnit(object):
Returns a dictionary of BaseDimension:exponent pairs, describing the dimension of this unit.
"""
yield (self.dimension, 1)
def iter_base_units(self):
yield (self, 1)
def get_dimension_tuple(self):
"""
Returns a sorted tuple of (BaseDimension, exponent) pairs, that can be used as a dictionary key.
......@@ -89,7 +89,7 @@ class BaseUnit(object):
l = list(self.iter_base_dimensions())
l.sort()
return tuple(l)
def __str__(self):
"""Returns a string with the name of this BaseUnit
"""
......@@ -97,40 +97,40 @@ class BaseUnit(object):
def __repr__(self):
return 'BaseUnit(base_dim=%s, name="%s", symbol="%s")' % (self.dimension, self.name, self.symbol)
def define_conversion_factor_to(self, other, factor):
"""
Defines a conversion factor between two BaseUnits.
self * factor = other
Parameters:
- self: (BaseUnit) 'From' unit in conversion.
- other: (BaseUnit) 'To' unit in conversion.
- factor: (float) Conversion factor.
After calling this method, both self and other will have stored
conversion factors for one another, plus all other BaseUnits which
self and other have previously defined.
Both self and other must have the same dimension, otherwise a TypeError
will be raised.
Returns None.
"""
if self.dimension != other.dimension:
raise TypeError('Cannot define conversion for BaseUnits with different dimensions.')
assert(factor != 0)
assert(not self is other)
assert(not self is other)
# import all transitive conversions
self._conversion_factor_to[other] = factor
self._conversion_factor_to_by_name[other.name] = factor
for (unit, cfac) in other._conversion_factor_to.items():
if unit is self: continue
if self._conversion_factor_to.has_key(unit): continue
self._conversion_factor_to[unit] = factor * cfac
self._conversion_factor_to[unit] = factor * cfac
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
unit._conversion_factor_to_by_name[self.name] = pow(factor * cfac, -1)
# and for the other guy
invFac = pow(factor, -1.0)
......@@ -146,13 +146,13 @@ class BaseUnit(object):
def conversion_factor_to(self, other):
"""Returns a conversion factor from this BaseUnit to another BaseUnit.
It does not matter which existing BaseUnit you define the conversion factor to.
Conversions for all other known BaseUnits will be computed at the same time.
Raises TypeError if dimension does not match.
Raises LookupError if no conversion has been defined. (see define_conversion_factor_to).
"""
if self is other: return 1.0
if self.dimension != other.dimension:
......
......@@ -11,7 +11,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......
......@@ -17,7 +17,7 @@ Examples
>>> furlong_base_unit.define_conversion_factor_to(meter_base_unit, 201.16800)
>>> furlong_base_unit.conversion_factor_to(angstrom_base_unit)
2011680000000.0
Examples
>>> furlong_base_unit = BaseUnit(length_dimension, "furlong", "fur")
......@@ -32,7 +32,7 @@ from unit.is_unit
True
>>> is_unit(5*meter)
False
>>> c = 1.0*calories
>>> c
Quantity(value=1.0, unit=calorie)
......@@ -166,7 +166,7 @@ Examples
>>> meter.is_compatible(centimeter)
True
>>> meter.is_compatible(meter)
>>> meter.is_compatible(meter)
True
>>> meter.is_compatible(kelvin)
False
......@@ -261,20 +261,20 @@ Collections of numbers can also be used as values.
Numpy examples are commented out because not all systems have numpy installed
# >>> import numpy
# >>>
# >>>
# >>> a = Quantity(numpy.array([1,2,3]), centimeters)
# >>> print(a)
# [1 2 3] cm
# >>> print(a / millimeters)
# [ 10. 20. 30.]
# >>>
# >>>
# >>> a2 = Quantity(numpy.array([[1,2,3],[4,5,6]]), centimeters)
# >>> print(a2)
# [[1 2 3]
# [4 5 6]] cm
# >>> print(a2 / millimeters)
# [[ 10. 20. 30.]
# [ 40. 50. 60.]]
# [ 40. 50. 60.]]
Addition, subtraction, multiplication, division, and powers of Quantities
exhibit correct dimensional analysis and unit conversion.
......@@ -293,12 +293,12 @@ The following examples are derived from the C++ Boost.Units examples at
http://www.boost.org/doc/libs/1_37_0/doc/html/boost_units/Examples.html
>>>
>>> l = 2.0 * meters
>>>
>>>
>>> print(l + 2.0 * nanometers)
2.000000002 m
>>> print(2.0 * nanometers + l)
2000000002.0 nm
>>>
>>>
>>> print(l)
2.0 m
>>> print(l+l)
......@@ -410,25 +410,25 @@ True
False
>>> print(l1 > l2)
False
>>>
>>>
>>> def work(f, dx):
... return f * dx
...
...
>>> F = 1.0 * kilogram * meter / second**2
>>> dx = 1.0 * meter
>>> E = work(F, dx)
>>>
>>>
>>> print("F = ", F)
F = 1.0 kg m/(s**2)
>>> print("dx = ", dx)
dx = 1.0 m
>>>
>>>
>>> def idealGasLaw(P, V, T):
... R = MOLAR_GAS_CONSTANT_R
... print("P * V = ", P * V)
... print("R * T = ", R * T)
... return (P * V / (R * T)).in_units_of(mole)
...
...
>>> T = (273.0 + 37.0) * kelvin
>>> P = 1.01325e5 * pascals
>>> r = 0.5e-6 * meters
......@@ -437,7 +437,7 @@ dx = 1.0 m
P * V = 5.3053601125e-14 m**3 Pa
R * T = 2577.48646608 J/mol
>>> R = MOLAR_GAS_CONSTANT_R
>>>
>>>
>>> print("r = ", r)
r = 5e-07 m
>>> print("P = ", P)
......@@ -460,7 +460,7 @@ is_quantity(V) = True
57.2957795131 deg
>>> print((1.0*angstroms).in_units_of(nanometers))
0.1 nm
>>>
>>>
>>> print((90*degrees)/radians)
1.57079632679
>>> print(sin(90*degrees))
......@@ -475,7 +475,7 @@ True
Traceback (most recent call last):
...
TypeError: Unit "degree" is not compatible with Unit "nanometer".
>>>
>>>
>>> x = 1.5 * nanometers
>>> print(x / meters)
1.5e-09
......@@ -503,7 +503,7 @@ Examples
10.0
>>> print(x.value_in_unit_system(md_unit_system))
100000000.0
>>>
>>>
>>> y = 20 * millimeters / millisecond**2
>>> print(y.value_in_unit_system(si_unit_system))
20000.0
......@@ -519,7 +519,7 @@ Examples
Dimensionless quantities return their unmodified values.
>>> Quantity(5, dimensionless).value_in_unit_system(md_unit_system)
5
Examples
>>> x = 2.3*meters
......@@ -581,9 +581,9 @@ Examples
>>> print(8.4 / x)
2.0 /cm
Examples
>>> x = 4.3 * meters
>>> print(x/centimeters)
430.0
......@@ -593,15 +593,15 @@ Examples
>>> x/millimeter
[10.0, 20.0, 30.0]
Examples
>>> x = 1.2*meters
>>> print(5*x)
6.0 m
Examples
>>> x = 1.2*meters
>>> y = 72*centimeters
>>> print(x*y)
......@@ -620,42 +620,42 @@ Examples
Quantity(value=2.0, unit=nanometer**2/(angstrom**2))
>>> "%.1f" % q.reduce_unit()
'200.0'
Examples
>>> 1.2*meters < 72*centimeters
False
>>> meter != None
True
>>> meter == None
False
Examples
>>> print(1.2 * meters - 72 * centimeters)
0.48 m
Examples
>>> print(1.2 * meters + 72 * centimeters)
1.92 m
Examples
>>> print(repr(1.2*meter))
Quantity(value=1.2, unit=meter)
Examples
>>> print(5.0 * nanometers)
5.0 nm
Examples
>>> Quantity(5.0, meters)
Quantity(value=5.0, unit=meter)
>>> Quantity([1*angstrom,2*nanometer,3*angstrom])
Quantity(value=[1, 20.0, 3], unit=angstrom)
>>> Quantity((1,2,3))
......@@ -684,14 +684,14 @@ Examples
>>> Quantity(value=5.0, unit=100.0*meters)
Quantity(value=500.0, unit=meter)
Examples
>>> x = 2.3*meters
>>> y = x.in_units_of(centimeters)
>>> print(y)
230.0 cm
>>> x = 2.3*meters
>>> print(x.in_units_of(centimeters))
230.0 cm
......@@ -699,9 +699,9 @@ Examples
Traceback (most recent call last):
...
TypeError: Unit "meter" is not compatible with Unit "second".
Examples
>>> x = 100.0 * millimeter
>>> print(x)
100.0 mm
......@@ -725,22 +725,22 @@ Examples
>>> q = 1.0 * md_kilocalorie/mole/angstrom
>>> print(q.in_units_of(md_kilojoule/mole/nanometer))
41.84 kJ/(nm mol)
Examples
>>> class Foo:
... def bar(self):
... print("bar")
...
...
>>> x = Foo()
>>> x.bar()
bar
>>> y = x * nanometers
>>> y.bar()
bar
Examples
>>> print(meters * centimeters)
centimeter*meter
>>> print(meters * meters)
......@@ -748,43 +748,43 @@ Examples
>>> print(meter * meter )
meter**2
Examples
>>> print(meter / 2)
0.5 m
Examples
>>> define_prefixed_units(kelvin_base_unit, sys.modules["__main__"])
>>> from __main__ import millikelvin
>>> print(5.0 * millikelvin)
5.0 mK
Creating a new BaseUnit:
>>> ms = milli * second_base_unit
>>> ms
BaseUnit(base_dim=BaseDimension("time"), name="millisecond", symbol="ms")
>>> ms.conversion_factor_to(second_base_unit)
0.001
Creating a new ScaledUnit:
>>> mC = milli * ScaledUnit(4.184, joule, "calorie", "cal")
>>> mC
ScaledUnit(factor=0.0041840000000000002, master=joule, name='millicalorie', symbol='mcal')
Creating a new Unit:
>>> ms = milli * second
>>> ms
Unit({BaseUnit(base_dim=BaseDimension("time"), name="millisecond", symbol="ms"): 1.0})
Don't try a Quantity though:
>>> ms = milli * (1.0 * second)
Traceback (most recent call last):
...
TypeError: Unit prefix "milli" can only be applied to a Unit, BaseUnit, or ScaledUnit.
Comparison of dimensionless quantities issue (fixed in svn 513)
>>> x = Quantity(1.0, dimensionless)
>>> y = Quantity(1.0, dimensionless)
......@@ -839,7 +839,7 @@ Examples
# April 2010, thanks to John Chodera for reporting
>>> try:
... import numpy
... x = Quantity(numpy.array([1.,2.]), nanometer)
... x = Quantity(numpy.array([1.,2.]), nanometer)
... y = Quantity(numpy.array([3.,4.]), picosecond)
... assert str(x/y) == '[ 0.33333333 0.5 ] nm/ps'
... except ImportError:
......
......@@ -10,7 +10,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......@@ -34,7 +34,7 @@ import sys
def eye(size):
"""
Returns identity matrix.
>>> print(eye(3))
[[1, 0, 0]
[0, 1, 0]
......@@ -50,11 +50,11 @@ def eye(size):
r.append(0)
result.append(r)
return MyMatrix(result)
def zeros(m, n=None):
"""
Returns matrix of zeroes
>>> print(zeros(3))
[[0, 0, 0]
[0, 0, 0]
......@@ -82,7 +82,7 @@ class MyVector(object):
def __str__(self):
return str(self.data)
def __repr__(self):
return self.__class__.__name__ + "(" + repr(self.data) + ")"
......@@ -91,20 +91,20 @@ class MyVector(object):
def __contains__(self, item):
return item in self.data
def __delitem__(self, key):
del self.data[key]
def __iter__(self):
for item in self.data:
yield item
def __len__(self):
return len(self.data)
def __setitem__(self, key, value):
self.data[key] = value
def __rmul__(self, lhs):
try:
len(lhs)
......@@ -119,7 +119,7 @@ class MyVector(object):
class MyMatrix(MyVector):
"""
Pure python linear algebra matrix for internal matrix inversion in UnitSystem.
>>> m = MyMatrix([[1,0,],[0,1,]])
>>> print(m)
[[1, 0]
......@@ -158,7 +158,7 @@ class MyMatrix(MyVector):
"""
def numRows(self):
return len(self.data)
def numCols(self):
if len(self.data) == 0:
return 0
......@@ -179,13 +179,13 @@ class MyMatrix(MyVector):
start_char = " "
result += "]"
return result
def __repr__(self):
return 'MyMatrix(' + MyVector.__repr__(self) + ')'
def is_square(self):
return self.numRows() == self.numCols()
def __iter__(self):
for item in self.data:
yield MyVector(item)
......@@ -206,7 +206,7 @@ class MyMatrix(MyVector):
def __mul__(self, rhs):
"""
Matrix multiplication.
>>> a = MyMatrix([[1,2],[3,4]])
>>> b = MyMatrix([[5,6],[7,8]])
>>> print(a)
......@@ -218,7 +218,7 @@ class MyMatrix(MyVector):
>>> print(a*b)
[[19, 22]
[43, 50]]
"""
m = self.numRows()
n = len(rhs[0])
......@@ -235,7 +235,7 @@ class MyMatrix(MyVector):
def __add__(self, rhs):
"""
Matrix addition.
>>> print(MyMatrix([[1, 2],[3, 4]]) + MyMatrix([[5, 6],[7, 8]]))
[[6, 8]
[10, 12]]
......@@ -253,7 +253,7 @@ class MyMatrix(MyVector):
def __sub__(self, rhs):
"""
Matrix subtraction.
>>> print(MyMatrix([[1, 2],[3, 4]]) - MyMatrix([[5, 6],[7, 8]]))
[[-4, -4]
[-4, -4]]
......@@ -270,7 +270,7 @@ class MyMatrix(MyVector):
def __pos__(self):
return self
def __neg__(self):
m = self.numRows()
n = self.numCols()
......@@ -384,7 +384,7 @@ class MyMatrix(MyVector):
for k in range(0,n):
temp = a[k][indxr[l]]
a[k][indxr[l]] = a[k][indxc[l]]
a[k][indxc[l]] = temp
a[k][indxc[l]] = temp
return a
def transpose(self):
......@@ -395,13 +395,13 @@ class MyMatrixTranspose(MyMatrix):
def transpose(self):
return MyMatrix(self.data)
def numRows(self):
if len(self.data) == 0:
return 0
else:
return len(self.data[0])
def numCols(self):
return len(self.data)
......@@ -461,7 +461,7 @@ class MyMatrixTranspose(MyMatrix):
# run module directly for testing
if __name__=='__main__':
# Test the examples in the docstrings
import doctest, sys
doctest.testmod(sys.modules[__name__])
......@@ -11,7 +11,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......@@ -44,14 +44,14 @@ import sys
class SiPrefix(object):
"""
Unit prefix that can be multiplied by a unit to yield a new unit.
e.g. millimeter = milli*meter
"""
def __init__(self, prefix, factor, symbol):
self.prefix = prefix
self.factor = factor
self.symbol = symbol
def __mul__(self, unit):
"""
SiPrefix * BaseUnit yields new BaseUnit
......@@ -136,7 +136,7 @@ si_prefixes = ( yotto
def define_prefixed_units(base_unit, module = sys.modules[__name__]):
"""
Create attributes for prefixed units derived from a particular BaseUnit, e.g. "kilometer" from "meter_base_unit"
Parameters
- base_unit (BaseUnit) existing base unit to use as a basis for prefixed units
- module (Module) module which will contain the new attributes. Defaults to simtk.unit module.
......@@ -146,7 +146,7 @@ def define_prefixed_units(base_unit, module = sys.modules[__name__]):
name = new_base_unit.name
new_unit = Unit({new_base_unit: 1.0})
# Create base_unit attribute, needed for creating UnitSystems
module.__dict__[name + '_base_unit'] = new_base_unit # e.g. "kilometer_base_unit"
module.__dict__[name + '_base_unit'] = new_base_unit # e.g. "kilometer_base_unit"
# Create attribue in this module
module.__dict__[name] = new_unit # e.g. "kilometer"
# And plural version
......
......@@ -10,7 +10,7 @@ In particular, there is no underlying set of 'canonical' base
units, whereas in Scientific.Physics.PhysicalQuantities all
units are secretly in terms of SI units. Also, it is easier
to add new fundamental dimensions to simtk.dimensions. You
might want to make new dimensions for, say, "currency" or
might want to make new dimensions for, say, "currency" or
"information".
Some features of this implementation:
......@@ -23,15 +23,15 @@ Some features of this implementation:
ones are predefined.
* Conversion factors between units are applied transitively, so all
possible conversions are available.
* I want dimensioned Quantities that are compatible with numpy arrays,
but do not necessarily require the python numpy package. In other
words, Quantities can be based on either numpy arrays or on built in
* I want dimensioned Quantities that are compatible with numpy arrays,
but do not necessarily require the python numpy package. In other
words, Quantities can be based on either numpy arrays or on built in
python types.
* Units are NOT necessarily stored in terms of SI units internally.
This is very important for me, because one important application
area for us is at the molecular scale. Using SI units internally
can lead to exponent overflow in commonly used molecular force
calculations. Internally, all unit systems are equally fundamental
* Units are NOT necessarily stored in terms of SI units internally.
This is very important for me, because one important application
area for us is at the molecular scale. Using SI units internally
can lead to exponent overflow in commonly used molecular force
calculations. Internally, all unit systems are equally fundamental
in SimTK.
Two possible enhancements that have not been implemented are
......@@ -49,7 +49,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......@@ -81,7 +81,7 @@ from unit import Unit, is_unit, dimensionless
class Quantity(object):
"""Physical quantity, such as 1.3 meters per second.
Quantities contain both a value, such as 1.3; and a unit,
such as 'meters per second'.
......@@ -92,7 +92,7 @@ class Quantity(object):
Note - unit conversions will cause tuples to be converted to lists
4 - lists of tuples of numbers, lists of lists of ... etc. of numbers
5 - numpy.arrays
Create numpy.arrays with units using the Quantity constructor, not the
multiply operator. e.g.
......@@ -104,11 +104,11 @@ class Quantity(object):
because numpy.arrays already overload the multiply operator for EVERYTHING.
"""
def __init__(self, value=None, unit=None):
"""
Create a new Quantity from a value and a unit.
Parameters
- value: (any type, usually a number) Measure of this quantity
- unit: (Unit) the physical unit, e.g. simtk.unit.meters.
......@@ -161,18 +161,18 @@ class Quantity(object):
else:
# Non-Quantity, non container
# Wrap in a dimensionless Quantity
unit = dimensionless
unit = dimensionless
# Accept simple scalar quantities as units
if is_quantity(unit):
value = value * unit._value
unit = unit.unit
# Use empty list for unspecified values
if value == None:
value = []
value = []
self._value = value
self.unit = unit
def __getstate__(self):
state = dict()
state['_value'] = self._value
......@@ -204,33 +204,33 @@ class Quantity(object):
"""
ret_val = getattr(self._value, attribute)
return ret_val
def __str__(self):
"""Printable string version of this Quantity.
Returns a string consisting of quantity number followed by unit abbreviation.
"""
return str(self._value) + ' ' + str(self.unit.get_symbol())
def __repr__(self):
"""
"""
return (Quantity.__name__ + '(value=' + repr(self._value) + ', unit=' +
str(self.unit) + ')')
def format(self, format_spec):
return format_spec % self._value + ' ' + str(self.unit.get_symbol())
def __add__(self, other):
"""Add two Quantities.
Only Quantities with the same dimensions (e.g. length)
can be added. Raises TypeError otherwise.
Parameters
- self: left hand member of sum
- other: right hand member of sum
Returns a new Quantity that is the sum of the two arguments.
"""
# can only add using like units
......@@ -242,14 +242,14 @@ class Quantity(object):
def __sub__(self, other):
"""Subtract two Quantities.
Only Quantities with the same dimensions (e.g. length)
can be subtracted. Raises TypeError otherwise.
Parameters
- self: left hand member (a) of a - b.
- other: right hand member (b) of a - b.
Returns a new Quantity that is the difference of the two arguments.
"""
if not self.unit.is_compatible(other.unit):
......@@ -257,7 +257,7 @@ class Quantity(object):
value = self._value - other.value_in_unit(self.unit)
unit = self.unit
return Quantity(value, unit)
def __eq__(self, other):
"""
"""
......@@ -266,7 +266,7 @@ class Quantity(object):
if not self.unit.is_compatible(other.unit):
return False
return self.value_in_unit(other.unit) == other._value
def __ne__(self, other):
"""
"""
......@@ -274,21 +274,21 @@ class Quantity(object):
def __lt__(self, other):
"""Compares two quantities.
Raises TypeError if the Quantities are of different dimension (e.g. length vs. mass)
Returns True if self < other, False otherwise.
"""
return self._value < other.value_in_unit(self.unit)
def __ge__(self, other):
return self._value >= (other.value_in_unit(self.unit))
return self._value >= (other.value_in_unit(self.unit))
def __gt__(self, other):
return self._value > (other.value_in_unit(self.unit))
return self._value > (other.value_in_unit(self.unit))
def __le__(self, other):
return self._value <= (other.value_in_unit(self.unit))
return self._value <= (other.value_in_unit(self.unit))
def __lt__(self, other):
return self._value < (other.value_in_unit(self.unit))
return self._value < (other.value_in_unit(self.unit))
_reduce_cache = {}
......@@ -296,7 +296,7 @@ class Quantity(object):
"""
Combine similar component units and scale, to form an
equal Quantity in simpler units.
Returns underlying value type if unit is dimensionless.
"""
key = (self.unit, guide_unit)
......@@ -353,7 +353,7 @@ class Quantity(object):
def __mul__(self, other):
"""Multiply a quantity by another object
Returns a new Quantity that is the product of the self * other,
unless the resulting unit is dimensionless, in which case the
underlying value type is returned, instead of a Quantity.
......@@ -373,12 +373,12 @@ class Quantity(object):
else:
# print "quantity * scalar"
return self._change_units_with_factor(self.unit, other, post_multiply=False)
# value type might not be commutative for multiplication
def __rmul__(self, other):
"""Multiply a scalar by a Quantity
Returns a new Quantity with the same units as self, but with the value
Returns a new Quantity with the same units as self, but with the value
multiplied by other.
"""
if is_unit(other):
......@@ -391,7 +391,7 @@ class Quantity(object):
# print "scalar * quantity"
return self._change_units_with_factor(self.unit, other, post_multiply=True)
# return Quantity(other * self._value, self.unit)
def __truediv__(self, other):
"""Divide a Quantity by another object
......@@ -416,7 +416,7 @@ class Quantity(object):
def __rtruediv__(self, other):
"""Divide a scalar by a quantity.
Returns a new Quantity. The resulting units are the inverse of the self argument units.
"""
if is_unit(other):
......@@ -433,17 +433,17 @@ class Quantity(object):
def __pow__(self, exponent):
"""Raise a Quantity to a power.
Generally both the value and the unit of the Quantity are affected by this operation.
Returns a new Quantity equal to self**exponent.
"""
return Quantity(pow(self._value, exponent), pow(self.unit, exponent))
def sqrt(self):
"""
Returns square root of a Quantity.
Raises ArithmeticError if component exponents are not even.
This behavior can be changed if you present a reasonable real life case to me.
"""
......@@ -458,25 +458,25 @@ class Quantity(object):
def __abs__(self):
"""
Return absolute value of a Quantity.
The unit is unchanged. A negative value of self will result in a positive value
in the result.
"""
return Quantity(abs(self._value), self.unit)
def __pos__(self):
"""
Returns a reference to self.
"""
return Quantity(+(self._value), self.unit)
def __neg__(self):
"""Negate a Quantity.
Returns a new Quantity with a different sign on the value.
"""
return Quantity(-(self._value), self.unit)
def __nonzero__(self):
"""Returns True if value underlying Quantity is zero, False otherwise.
"""
......@@ -490,7 +490,7 @@ class Quantity(object):
return Quantity(int(self._value), self.unit)
def __long__(self):
return Quantity(int(self._value), self.unit)
def value_in_unit(self, unit):
"""
Returns underlying value, in the specified units.
......@@ -510,7 +510,7 @@ class Quantity(object):
return result._value
else:
return result # dimensionless
def in_unit_system(self, system):
"""
Returns a new Quantity equal to this one, expressed in a particular unit system.
......@@ -525,7 +525,7 @@ class Quantity(object):
If the units are the same as those in self, a reference to self is returned.
Raises a TypeError if the new unit is not compatible with the original unit.
The post_multiply argument is used in case the multiplication operation is not commutative.
i.e. result = factor * value when post_multiply is False
and result = value * factor when post_multiply is True
......@@ -534,7 +534,7 @@ class Quantity(object):
raise TypeError('Unit "%s" is not compatible with Unit "%s".' % (self.unit, other_unit))
f = self.unit.conversion_factor_to(other_unit)
return self._change_units_with_factor(other_unit, f)
def _change_units_with_factor(self, new_unit, factor, post_multiply=True):
# numpy arrays cannot be compared with 1.0, so just "try"
factor_is_identity = False
......@@ -555,7 +555,7 @@ class Quantity(object):
if post_multiply:
value = self._value * factor # works for number, numpy.array, or vec3, e.g.
else:
value = factor * self._value # works for number, numpy.array, or vec3, e.g.
value = factor * self._value # works for number, numpy.array, or vec3, e.g.
result = Quantity(value, new_unit)
except TypeError:
# list * float fails with TypeError
......@@ -614,7 +614,7 @@ class Quantity(object):
"""
assert not is_quantity(self._value[key])
return Quantity(self._value[key], self.unit)
def __setitem__(self, key, value):
# Delegate slices to one-at-a time ___setitem___
if isinstance(key, slice): # slice
......@@ -629,13 +629,13 @@ class Quantity(object):
raise TypeError('Unit "%s" is not compatible with Unit "%s".' % (self.unit, value.unit))
self._value[key] = value / self.unit
assert not is_quantity(self._value[key])
def __delitem__(self, key):
del(self._value[key])
def __contains__(self, item):
return self._value.__contains__(item.value_in_unit(self.unit))
def __iter__(self):
for item in self._value:
yield Quantity(item, self.unit)
......
......@@ -13,7 +13,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......
......@@ -13,7 +13,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......@@ -51,7 +51,7 @@ class Unit(object):
"""
def __init__(self, base_or_scaled_units):
"""Create a new Unit.
Parameters:
- self (Unit) The newly created Unit.
- base_or_scaled_units (dict) Keys are BaseUnits or ScaledUnits. Values are exponents (numbers).
......@@ -113,7 +113,7 @@ class Unit(object):
new_base_unit.define_conversion_factor_to(parent_base_unit, true_scale)
new_unit = Unit({new_base_unit: 1.0})
return new_unit
def iter_base_dimensions(self):
"""
Yields (BaseDimension, exponent) tuples comprising this unit.
......@@ -130,7 +130,7 @@ class Unit(object):
"""
Yields (BaseUnit, exponent) tuples comprising this unit, including those BaseUnits
found within ScaledUnits.
There might be multiple BaseUnits with the same dimension.
"""
for dimension in sorted(self._all_base_units.iterkeys()):
......@@ -146,7 +146,7 @@ class Unit(object):
for unit in sorted(self._top_base_units[dimension].iterkeys()):
exponent = self._top_base_units[dimension][unit]
yield (unit, exponent)
def iter_scaled_units(self):
for unit, exponent in self._scaled_units:
yield (unit, exponent)
......@@ -169,7 +169,7 @@ class Unit(object):
# print scaled_unit.factor
factor *= scaled_unit.factor ** exponent
return factor
def __eq__(self, other):
if not is_unit(other):
return False
......@@ -180,9 +180,9 @@ class Unit(object):
def __lt__(self, other):
"""Compare two Units.
Raises a TypeError if the units have different dimensions.
Returns True if self < other, False otherwise.
"""
if not self.is_compatible(other):
......@@ -202,12 +202,12 @@ class Unit(object):
# def __mul__(self, other):
# See unit_operators.py for Unit.__mul__ operator
def __truediv__(self, other):
"""Divide a Unit by another object.
Returns a composite Unit if other is another Unit.
Returns a Quantity otherwise. UNLESS other is a Quantity AND
the resulting unit type is dimensionless, in which case the underlying
value type of the Quantity is returned.
......@@ -223,7 +223,7 @@ class Unit(object):
def __pow__(self, exponent):
"""Raise a Unit to a power.
Returns a new Unit with different exponents on the BaseUnits.
"""
if self in Unit._pow_cache:
......@@ -241,7 +241,7 @@ class Unit(object):
def sqrt(self):
"""
Returns square root of a unit.
Raises ArithmeticError if component exponents are not even.
This behavior can be changed if you present a reasonable real life case to me.
"""
......@@ -280,7 +280,7 @@ class Unit(object):
def __str__(self):
"""Returns the human-readable name of this unit"""
return self.get_name()
def __repr__(self):
"""
Returns a unit name (string) for this Unit, composed of its various
......@@ -321,7 +321,7 @@ class Unit(object):
Unit._is_compatible_cache[self] = {}
Unit._is_compatible_cache[self][other] = result
return result
_is_dimensionless_cache = {}
def is_dimensionless(self):
......@@ -336,7 +336,7 @@ class Unit(object):
return False
Unit._is_dimensionless_cache[self] = True
return True
# Performance
_conversion_factor_cache = {}
......@@ -344,7 +344,7 @@ class Unit(object):
"""
Returns conversion factor for computing all of the common dimensions
between self and other from self base units to other base units.
The two units need not share all of the same dimensions. In case they
do not, the conversion factor applies only to the BaseUnits of self
that correspond to different BaseUnits in other.
......@@ -352,7 +352,7 @@ class Unit(object):
This method requires strict compatibility between the two units.
"""
factor = 1.0
if (self is other):
if (self is other):
return factor
if self in Unit._conversion_factor_cache:
if other in Unit._conversion_factor_cache[self]:
......@@ -385,9 +385,9 @@ class Unit(object):
def in_unit_system(self, system):
"""
Returns a new Unit with the same dimensions as this one, expressed in a particular unit system.
Strips off any ScaledUnits in the Unit, leaving only BaseUnits.
Parameters
- system: a dictionary of (BaseDimension, BaseUnit) pairs
"""
......@@ -402,7 +402,7 @@ class Unit(object):
# emit positive exponents first
pos = ""
pos_count = 0
for unit, power in self.iter_base_or_scaled_units():
for unit, power in self.iter_base_or_scaled_units():
if power > 0:
pos_count += 1
if pos_count > 1: pos += " "
......@@ -413,7 +413,7 @@ class Unit(object):
neg = ""
neg_count = 0
simple_denominator = True
for unit, power in self.iter_base_or_scaled_units():
for unit, power in self.iter_base_or_scaled_units():
if power < 0:
neg_count += 1
if neg_count > 1: neg += " "
......@@ -421,7 +421,7 @@ class Unit(object):
if power != -1.0:
neg += "**%g" % -power
simple_denominator = False
# Format of denominator depends on number of terms
# Format of denominator depends on number of terms
if 0 == neg_count:
neg_string = ""
elif 1 == neg_count and simple_denominator:
......@@ -450,7 +450,7 @@ class Unit(object):
# emit positive exponents first
pos = ""
pos_count = 0
for unit, power in self.iter_base_or_scaled_units():
for unit, power in self.iter_base_or_scaled_units():
if power > 0:
pos_count += 1
if pos_count > 1: pos += "*"
......@@ -461,7 +461,7 @@ class Unit(object):
neg = ""
neg_count = 0
simple_denominator = True
for unit, power in self.iter_base_or_scaled_units():
for unit, power in self.iter_base_or_scaled_units():
if power < 0:
neg_count += 1
if neg_count > 1: neg += "*"
......@@ -469,7 +469,7 @@ class Unit(object):
if power != -1.0:
neg += "**%g" % -power
simple_denominator = False
# Format of denominator depends on number of terms
# Format of denominator depends on number of terms
if 0 == neg_count:
neg_string = ""
elif 1 == neg_count and simple_denominator:
......@@ -491,7 +491,7 @@ class Unit(object):
class ScaledUnit(object):
"""
ScaledUnit is like a BaseUnit, but it is based on another Unit.
ScaledUnit and BaseUnit are both used in the internals of Unit. They
should only be used during the construction of Units.
"""
......@@ -536,10 +536,10 @@ class ScaledUnit(object):
l = list(self.iter_base_dimensions())
l.sort()
return tuple(l)
def get_conversion_factor_to_base_units(self):
return self.factor
def conversion_factor_to(self, other):
# Create fake unit based on base units
if self is other:
......@@ -557,7 +557,7 @@ class ScaledUnit(object):
"""Compare two ScaledUnits.
"""
return hash(self) < hash(other)
def __str__(self):
"""Returns a string with the name of this ScaledUnit
"""
......@@ -610,7 +610,7 @@ class UnitSystem(object):
# except ArithmeticError:
# e=sys.exc_info[1]
raise ArithmeticError("UnitSystem is not a valid basis set. " + str(e))
def __iter__(self):
for unit in self.units:
yield unit
......@@ -667,14 +667,14 @@ class UnitSystem(object):
def is_unit(x):
"""
Returns True if x is a Unit, False otherwise.
Examples
>>> is_unit(16)
False
"""
return isinstance(x, Unit)
dimensionless = Unit({})
# run module directly for testing
......
......@@ -11,7 +11,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......
......@@ -13,7 +13,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......@@ -49,7 +49,7 @@ from unit_definitions import *
def sin(angle):
"""
Examples
>>> sin(90*degrees)
1.0
"""
......@@ -67,7 +67,7 @@ def sinh(angle):
def cos(angle):
"""
Examples
>>> cos(180*degrees)
-1.0
"""
......@@ -102,10 +102,10 @@ def acos(x):
0.0 rad
"""
return math.acos(x) * radians
def acosh(x):
return math.acosh(x) * radians
def asin(x):
return math.asin(x) * radians
......@@ -114,10 +114,10 @@ def asinh(x):
def atan(x):
return math.atan(x) * radians
def atanh(x):
return math.atanh(x) * radians
def atan2(x, y):
return math.atan2(x, y) * radians
......
......@@ -10,7 +10,7 @@ In particular, there is no underlying set of 'canonical' base
units, whereas in Scientific.Physics.PhysicalQuantities all
units are secretly in terms of SI units. Also, it is easier
to add new fundamental dimensions to simtk.dimensions. You
might want to make new dimensions for, say, "currency" or
might want to make new dimensions for, say, "currency" or
"information".
Two possible enhancements that have not been implemented are
......@@ -28,7 +28,7 @@ Portions copyright (c) 2012 Stanford University and the Authors.
Authors: Christopher M. Bruns
Contributors: Peter Eastman
Permission is hereby granted, free of charge, to any person obtaining a
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
......@@ -60,7 +60,7 @@ from quantity import Quantity, is_quantity
def _unit_class_rdiv(self, other):
"""
Divide another object type by a Unit.
Returns a new Quantity with a value of other and units
of the inverse of self.
"""
......@@ -78,14 +78,14 @@ Unit.__rdiv__ = _unit_class_rdiv
def _unit_class_mul(self, other):
"""Multiply a Unit by an object.
If other is another Unit, returns a new composite Unit.
Exponents of similar dimensions are added. If self and
If other is another Unit, returns a new composite Unit.
Exponents of similar dimensions are added. If self and
other share similar BaseDimension, but
with different BaseUnits, the resulting BaseUnit for that
BaseDimension will be that used in self.
If other is a not another Unit, this method returns a
If other is a not another Unit, this method returns a
new Quantity... UNLESS other is a Quantity and the resulting
unit is dimensionless, in which case the underlying value type
of the Quantity is returned.
......@@ -133,7 +133,7 @@ def _unit_class_mul(self, other):
# Is reduce_unit needed here? I hope not, there is a performance issue...
# return Quantity(other, self).reduce_unit(self)
return Quantity(other, self)
Unit.__mul__ = _unit_class_mul
Unit.__rmul__ = Unit.__mul__
Unit._multiplication_cache = {}
......
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