Skip to content

Commit 74ebd5c

Browse files
committed
enable mixed-unit addition and subtraction when units can be converted
1 parent c2a5e47 commit 74ebd5c

File tree

6 files changed

+44
-7
lines changed

6 files changed

+44
-7
lines changed

.eric4project/quantities.e4q

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE UserProject SYSTEM "UserProject-4.0.dtd">
33
<!-- eric4 user project file for project quantities -->
4-
<!-- Saved: 2009-10-12, 12:46:11 -->
4+
<!-- Saved: 2009-10-12, 16:52:56 -->
55
<!-- Copyright (C) 2009 , -->
66
<UserProject version="4.0">
77
</UserProject>

.eric4project/quantities.e4t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE Tasks SYSTEM "Tasks-4.2.dtd">
33
<!-- eric4 tasks file for project quantities -->
4-
<!-- Saved: 2009-10-12, 12:46:11 -->
4+
<!-- Saved: 2009-10-12, 16:52:56 -->
55
<Tasks version="4.2">
66
<Task priority="1" completed="False" bugfix="False">
77
<Summary>TODO: move to constants</Summary>

quantities/quantity.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,13 @@ def get_conversion_factor(from_u, to_u):
4747
assert from_u.dimensionality == to_u.dimensionality
4848
return from_u.magnitude / to_u.magnitude
4949

50-
def protected_addition(f):
50+
def scale_other_units(f):
5151
@wraps(f)
5252
def g(self, other, *args):
5353
if not isinstance(other, Quantity):
5454
other = Quantity(other, copy=False)
55-
getattr(self._dimensionality, f.__name__)(other._dimensionality)
55+
if other._dimensionality != self._dimensionality:
56+
other = other.rescale(self.units)
5657
return f(self, other, *args)
5758
return g
5859

@@ -224,13 +225,33 @@ def __array_wrap__(self, obj, context=None):
224225
print 'https://bugs.launchpad.net/python-quantities'
225226
return result
226227

228+
@with_doc(np.ndarray.__add__)
229+
@scale_other_units
230+
def __add__(self, other):
231+
return super(Quantity, self).__add__(other)
232+
233+
@with_doc(np.ndarray.__radd__)
234+
@scale_other_units
235+
def __radd__(self, other):
236+
return super(Quantity, self).__radd__(other)
237+
227238
@with_doc(np.ndarray.__iadd__)
228-
@protected_addition
239+
@scale_other_units
229240
def __iadd__(self, other):
230241
return super(Quantity, self).__iadd__(other)
231242

243+
@with_doc(np.ndarray.__sub__)
244+
@scale_other_units
245+
def __sub__(self, other):
246+
return super(Quantity, self).__sub__(other)
247+
248+
@with_doc(np.ndarray.__rsub__)
249+
@scale_other_units
250+
def __rsub__(self, other):
251+
return super(Quantity, self).__rsub__(other)
252+
232253
@with_doc(np.ndarray.__isub__)
233-
@protected_addition
254+
@scale_other_units
234255
def __isub__(self, other):
235256
return super(Quantity, self).__isub__(other)
236257

quantities/tests/test_25_quantity_arithmetic.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ def test_mul():
126126
yield check(check_rmul, x, y)
127127
dtypes.pop(0)
128128

129+
def test_mixed_addition():
130+
assert_quantity_almost_equal(1*pq.ft + 1*pq.m, 4.280839895 * pq.ft)
131+
assert_quantity_almost_equal(pq.ft + pq.m, 4.280839895 * pq.ft)
129132

130133
#def test_negative():
131134
# assert_array_equal(

quantities/tests/test_30_quantity_conversion.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ def test_quantity_creation():
1515
assert_raises(LookupError, pq.Quantity, 1, 'nonsense')
1616
assert_equal(str(pq.Quantity(1, '')), '1 dimensionless')
1717

18+
def test_unit_conversion():
19+
x = pq.Quantity(10., 'm')
20+
x.units = pq.ft
21+
assert_quantity_almost_equal(x, 32.80839895 * pq.ft)
22+
23+
x = 10 * pq.m
24+
x.units = pq.ft
25+
assert_quantity_almost_equal(x, 32.80839895 * pq.ft)
26+
1827
def test_compound_reduction():
1928

2029
pc_per_cc = pq.CompoundUnit("pc/cm**3")

quantities/uncertainquantity.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import numpy as np
77

88
from . import markup
9-
from .quantity import Quantity
9+
from .quantity import Quantity, scale_other_units
1010
from .registry import unit_registry
1111
from .utilities import with_doc
1212

@@ -86,22 +86,26 @@ def __array_finalize__(self, obj):
8686
)
8787

8888
@with_doc(Quantity.__add__, use_header=False)
89+
@scale_other_units
8990
def __add__(self, other):
9091
res = super(UncertainQuantity, self).__add__(other)
9192
u = (self.uncertainty**2+other.uncertainty**2)**0.5
9293
return UncertainQuantity(res, uncertainty=u, copy=False)
9394

9495
@with_doc(Quantity.__radd__, use_header=False)
96+
@scale_other_units
9597
def __radd__(self, other):
9698
return self.__add__(other)
9799

98100
@with_doc(Quantity.__sub__, use_header=False)
101+
@scale_other_units
99102
def __sub__(self, other):
100103
res = super(UncertainQuantity, self).__sub__(other)
101104
u = (self.uncertainty**2+other.uncertainty**2)**0.5
102105
return UncertainQuantity(res, uncertainty=u, copy=False)
103106

104107
@with_doc(Quantity.__rsub__, use_header=False)
108+
@scale_other_units
105109
def __rsub__(self, other):
106110
if not isinstance(other, UncertainQuantity):
107111
other = UncertainQuantity(other, copy=False)

0 commit comments

Comments
 (0)