[yt-svn] commit/yt: 2 new changesets

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Thu May 12 06:55:00 PDT 2016


2 new commits in yt:

https://bitbucket.org/yt_analysis/yt/commits/100c520a9d33/
Changeset:   100c520a9d33
Branch:      yt
User:        ngoldbaum
Date:        2016-05-10 21:04:50+00:00
Summary:     Allow adding or subtracting arrays filled with zeros without checking units

This is a behavior change that allows the python builtin sum() function to work
correctly. It also matches the behavior of astropy's units.

Overall this should have minimal performance implications for scripts that did
not raise errors before this pull request, since most code changes are in paths
that would have raised errors before.

There is one place where we need to see if there are any nonzero elements in
either array to ensure that units are propogated properly. Hopefully for most
real data that isn't filled with zeros this will be a relatively fast, but it
is a bit of overhead. Any suggestions on how to avoid doing it would be very
much appreciated.

I've also added tests for this new behavior, and added a test for the `sum`
builtin when applied to a YTArray.
Affected #:  2 files

diff -r 78591f39a47d294c9ff8d5be7121fbe51e5a2acd -r 100c520a9d33f7529d2421fb52ec48244898e339 yt/units/tests/test_ytarray.py
--- a/yt/units/tests/test_ytarray.py
+++ b/yt/units/tests/test_ytarray.py
@@ -112,6 +112,20 @@
     yield assert_raises, YTUnitOperationError, operator.add, a1, a2
     yield assert_raises, YTUnitOperationError, operator.iadd, a1, a2
 
+    # adding with zero is allowed irrespective of the units
+    zeros = np.zeros(3)
+    zeros_yta_dimless = YTArray(zeros, 'dimensionless')
+    zeros_yta_length = YTArray(zeros, 'm')
+    zeros_yta_mass = YTArray(zeros, 'kg')
+    operands = [0, YTQuantity(0), YTQuantity(0, 'kg'), zeros, zeros_yta_dimless,
+                zeros_yta_length, zeros_yta_mass]
+
+    for op in [operator.add, np.add]:
+        for operand in operands:
+            yield operate_and_compare, a1, operand, op, a1
+            yield operate_and_compare, operand, a1, op, a1
+            yield operate_and_compare, 4*m, operand, op, 4*m
+            yield operate_and_compare, operand, 4*m, op, 4*m
 
 def test_subtraction():
     """
@@ -173,6 +187,20 @@
     yield assert_raises, YTUnitOperationError, operator.sub, a1, a2
     yield assert_raises, YTUnitOperationError, operator.isub, a1, a2
 
+    # subtracting with zero is allowed irrespective of the units
+    zeros = np.zeros(3)
+    zeros_yta_dimless = YTArray(zeros, 'dimensionless')
+    zeros_yta_length = YTArray(zeros, 'm')
+    zeros_yta_mass = YTArray(zeros, 'kg')
+    operands = [0, YTQuantity(0), YTQuantity(0, 'kg'), zeros, zeros_yta_dimless,
+                zeros_yta_length, zeros_yta_mass]
+
+    for op in [operator.sub, np.subtract]:
+        for operand in operands:
+            yield operate_and_compare, a1, operand, op, a1
+            yield operate_and_compare, operand, a1, op, -a1
+            yield operate_and_compare, 4*m, operand, op, 4*m
+            yield operate_and_compare, operand, 4*m, op, -4*m
 
 def test_multiplication():
     """
@@ -1163,3 +1191,10 @@
         degree_values = np.random.random(10)*degree
         radian_values = degree_values.in_units('radian')
         assert_array_equal(ufunc(degree_values), ufunc(radian_values))
+
+def test_builtin_sum():
+    from yt.units import km
+
+    arr = [1, 2, 3]*km
+    assert_equal(sum(arr), 6*km)
+

diff -r 78591f39a47d294c9ff8d5be7121fbe51e5a2acd -r 100c520a9d33f7529d2421fb52ec48244898e339 yt/units/yt_array.py
--- a/yt/units/yt_array.py
+++ b/yt/units/yt_array.py
@@ -148,12 +148,18 @@
     # attribute.
     if isinstance(ret, YTArray):
         if not inp.units.same_dimensions_as(ret.units):
+            # handle special case of adding or subtracting with zero or
+            # array filled with zero
+            if not np.any(other_object):
+                return ret.view(np.ndarray)
+            elif not np.any(this_object):
+                return ret
             raise YTUnitOperationError(op_string, inp.units, ret.units)
         ret = ret.in_units(inp.units)
-    # If the other object is not a YTArray, the only valid case is adding
-    # dimensionless things.
     else:
-        if not inp.units.is_dimensionless:
+        # If the other object is not a YTArray, then one of the arrays must be
+        # dimensionless or filled with zeros
+        if not inp.units.is_dimensionless and np.any(ret):
             raise YTUnitOperationError(op_string, inp.units, dimensionless)
     return ret
 
@@ -1202,13 +1208,21 @@
                     unit2 = 1.0
             unit_operator = self._ufunc_registry[context[0]]
             if unit_operator in (preserve_units, comparison_unit, arctan2_unit):
-                # Allow comparisons with dimensionless quantities.
-                if (unit1 != unit2 and
-                    not unit2.is_dimensionless and not unit1.is_dimensionless):
-                    if not unit1.same_dimensions_as(unit2):
-                        raise YTUnitOperationError(context[0], unit1, unit2)
-                    else:
-                        raise YTUfuncUnitError(context[0], unit1, unit2)
+                # Allow comparisons, addition, and subtraction with
+                # dimensionless quantities or arrays filled with zeros.
+                u1d = unit1.is_dimensionless
+                u2d = unit2.is_dimensionless
+                if unit1 != unit2:
+                    any_nonzero = [np.any(oper1), np.any(oper2)]
+                    if any_nonzero[0] is np.bool_(False):
+                        unit1 = unit2
+                    elif any_nonzero[1] is np.bool_(False):
+                        unit2 = unit1
+                    elif not any([u1d, u2d]):
+                        if not unit1.same_dimensions_as(unit2):
+                            raise YTUnitOperationError(context[0], unit1, unit2)
+                        else:
+                            raise YTUfuncUnitError(context[0], unit1, unit2)
             unit = unit_operator(unit1, unit2)
             if unit_operator in (multiply_units, divide_units):
                 if unit.is_dimensionless and unit.base_value != 1.0:


https://bitbucket.org/yt_analysis/yt/commits/bdf16ce177f5/
Changeset:   bdf16ce177f5
Branch:      yt
User:        jzuhone
Date:        2016-05-12 13:54:37+00:00
Summary:     Merged in ngoldbaum/yt (pull request #2171)

Allow adding or subtracting arrays filled with zeros without checking units
Affected #:  2 files

diff -r 6068831a37f4d92db1f3788c867e56efb286e587 -r bdf16ce177f5fd1d88b07c227b0e5759fba0ecea yt/units/tests/test_ytarray.py
--- a/yt/units/tests/test_ytarray.py
+++ b/yt/units/tests/test_ytarray.py
@@ -112,6 +112,20 @@
     yield assert_raises, YTUnitOperationError, operator.add, a1, a2
     yield assert_raises, YTUnitOperationError, operator.iadd, a1, a2
 
+    # adding with zero is allowed irrespective of the units
+    zeros = np.zeros(3)
+    zeros_yta_dimless = YTArray(zeros, 'dimensionless')
+    zeros_yta_length = YTArray(zeros, 'm')
+    zeros_yta_mass = YTArray(zeros, 'kg')
+    operands = [0, YTQuantity(0), YTQuantity(0, 'kg'), zeros, zeros_yta_dimless,
+                zeros_yta_length, zeros_yta_mass]
+
+    for op in [operator.add, np.add]:
+        for operand in operands:
+            yield operate_and_compare, a1, operand, op, a1
+            yield operate_and_compare, operand, a1, op, a1
+            yield operate_and_compare, 4*m, operand, op, 4*m
+            yield operate_and_compare, operand, 4*m, op, 4*m
 
 def test_subtraction():
     """
@@ -173,6 +187,20 @@
     yield assert_raises, YTUnitOperationError, operator.sub, a1, a2
     yield assert_raises, YTUnitOperationError, operator.isub, a1, a2
 
+    # subtracting with zero is allowed irrespective of the units
+    zeros = np.zeros(3)
+    zeros_yta_dimless = YTArray(zeros, 'dimensionless')
+    zeros_yta_length = YTArray(zeros, 'm')
+    zeros_yta_mass = YTArray(zeros, 'kg')
+    operands = [0, YTQuantity(0), YTQuantity(0, 'kg'), zeros, zeros_yta_dimless,
+                zeros_yta_length, zeros_yta_mass]
+
+    for op in [operator.sub, np.subtract]:
+        for operand in operands:
+            yield operate_and_compare, a1, operand, op, a1
+            yield operate_and_compare, operand, a1, op, -a1
+            yield operate_and_compare, 4*m, operand, op, 4*m
+            yield operate_and_compare, operand, 4*m, op, -4*m
 
 def test_multiplication():
     """
@@ -1163,3 +1191,10 @@
         degree_values = np.random.random(10)*degree
         radian_values = degree_values.in_units('radian')
         assert_array_equal(ufunc(degree_values), ufunc(radian_values))
+
+def test_builtin_sum():
+    from yt.units import km
+
+    arr = [1, 2, 3]*km
+    assert_equal(sum(arr), 6*km)
+

diff -r 6068831a37f4d92db1f3788c867e56efb286e587 -r bdf16ce177f5fd1d88b07c227b0e5759fba0ecea yt/units/yt_array.py
--- a/yt/units/yt_array.py
+++ b/yt/units/yt_array.py
@@ -148,12 +148,18 @@
     # attribute.
     if isinstance(ret, YTArray):
         if not inp.units.same_dimensions_as(ret.units):
+            # handle special case of adding or subtracting with zero or
+            # array filled with zero
+            if not np.any(other_object):
+                return ret.view(np.ndarray)
+            elif not np.any(this_object):
+                return ret
             raise YTUnitOperationError(op_string, inp.units, ret.units)
         ret = ret.in_units(inp.units)
-    # If the other object is not a YTArray, the only valid case is adding
-    # dimensionless things.
     else:
-        if not inp.units.is_dimensionless:
+        # If the other object is not a YTArray, then one of the arrays must be
+        # dimensionless or filled with zeros
+        if not inp.units.is_dimensionless and np.any(ret):
             raise YTUnitOperationError(op_string, inp.units, dimensionless)
     return ret
 
@@ -1202,13 +1208,21 @@
                     unit2 = 1.0
             unit_operator = self._ufunc_registry[context[0]]
             if unit_operator in (preserve_units, comparison_unit, arctan2_unit):
-                # Allow comparisons with dimensionless quantities.
-                if (unit1 != unit2 and
-                    not unit2.is_dimensionless and not unit1.is_dimensionless):
-                    if not unit1.same_dimensions_as(unit2):
-                        raise YTUnitOperationError(context[0], unit1, unit2)
-                    else:
-                        raise YTUfuncUnitError(context[0], unit1, unit2)
+                # Allow comparisons, addition, and subtraction with
+                # dimensionless quantities or arrays filled with zeros.
+                u1d = unit1.is_dimensionless
+                u2d = unit2.is_dimensionless
+                if unit1 != unit2:
+                    any_nonzero = [np.any(oper1), np.any(oper2)]
+                    if any_nonzero[0] is np.bool_(False):
+                        unit1 = unit2
+                    elif any_nonzero[1] is np.bool_(False):
+                        unit2 = unit1
+                    elif not any([u1d, u2d]):
+                        if not unit1.same_dimensions_as(unit2):
+                            raise YTUnitOperationError(context[0], unit1, unit2)
+                        else:
+                            raise YTUfuncUnitError(context[0], unit1, unit2)
             unit = unit_operator(unit1, unit2)
             if unit_operator in (multiply_units, divide_units):
                 if unit.is_dimensionless and unit.base_value != 1.0:

Repository URL: https://bitbucket.org/yt_analysis/yt/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.spacepope.org/pipermail/yt-svn-spacepope.org/attachments/20160512/f6561fd6/attachment-0002.htm>


More information about the yt-svn mailing list