diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index 223432e076..dbb8b506d1 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -386,8 +386,8 @@ def exponentiate(cube, exponent, in_place=False): """ _assert_is_cube(cube) - def power(data, out=None): - return np.power(data, exponent, out) + def power(data): + return biggus.power(data, exponent) return _math_op_common(cube, power, cube.units ** exponent, in_place=in_place) @@ -656,11 +656,7 @@ def _math_op_common(cube, operation_function, new_unit, in_place=False): _assert_is_cube(cube) if in_place: new_cube = cube - try: - operation_function(new_cube._my_data, out=new_cube._my_data) - except TypeError: - # Non ufunc function - operation_function(new_cube.data) + new_cube._my_data = operation_function(new_cube._my_data) else: new_cube = cube.copy(data=operation_function(cube._my_data)) iris.analysis.clear_phenomenon_identity(new_cube) diff --git a/lib/iris/tests/test_basic_maths.py b/lib/iris/tests/test_basic_maths.py index e690805140..8ce0eefa12 100644 --- a/lib/iris/tests/test_basic_maths.py +++ b/lib/iris/tests/test_basic_maths.py @@ -562,10 +562,10 @@ def vec_mag(u, v): vec_mag_ufunc = np.frompyfunc(vec_mag, 2, 1) b = iris.analysis.maths.apply_ufunc(vec_mag_ufunc, a, c) - ans = a.data**2 + c.data**2 - b2 = b**2 + ans = np.sqrt(a.data**2 + c.data**2) + # b2 = b**2 - self.assertArrayAlmostEqual(b2.data, ans) + self.assertArrayAlmostEqual(b.data, ans) class TestIFunc(tests.IrisTest): def setUp(self): diff --git a/lib/iris/tests/unit/analysis/maths/test_exponentiate.py b/lib/iris/tests/unit/analysis/maths/test_exponentiate.py new file mode 100644 index 0000000000..98aa7ef228 --- /dev/null +++ b/lib/iris/tests/unit/analysis/maths/test_exponentiate.py @@ -0,0 +1,94 @@ +# (C) British Crown Copyright 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the :func:`iris.analysis.maths.exponentiate` function.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests +from iris.tests.stock import simple_2d + +from biggus import NumpyArrayAdapter +import iris +from iris.analysis.maths import exponentiate +import numpy as np + + +class Test_exponentiate(tests.IrisTest): + def setUp(self): + self.cube = simple_2d(with_bounds=False) + self.exponent = np.float32(2) + + def test_basic(self): + expected = self.cube.data ** self.exponent + result = exponentiate(self.cube, self.exponent) + self.assertArrayEqual(result.data, expected) + + def test_masked(self): + cube = self.cube.copy() + mask = cube.data % 3 == 0 + masked_data = np.ma.masked_array(cube.data, mask) + cube.data = masked_data + expected = masked_data ** 2 + result = exponentiate(cube, self.exponent) + self.assertMaskedArrayEqual(result.data, expected) + + def test_lazy_data__inplace(self): + # Confirm that the cube's lazy data is preserved through an operation + # that is not in-place. + cube = self.cube.copy() + cube.lazy_data(array=NumpyArrayAdapter(cube.data)) + expected = cube.copy().data ** self.exponent + exponentiate(cube, self.exponent, in_place=True) + self.assertTrue(cube.has_lazy_data()) + self.assertArrayAlmostEqual(cube.data, expected) + + def test_lazy_data__not_inplace(self): + # Confirm that the cube's lazy data is preserved through an + # in-place operation. + cube = self.cube.copy() + cube.lazy_data(array=NumpyArrayAdapter(cube.data)) + expected = cube.copy().data ** self.exponent + result = exponentiate(cube, self.exponent, in_place=False) + self.assertTrue(result.has_lazy_data()) + self.assertArrayEqual(result.data, expected) + + def test_exponentiate__preloaded_data__inplace(self): + # Confirm that the cube's data is lazy after an in-place operation and + # after pre-loading the data. + cube = self.cube.copy() + cube.lazy_data(array=NumpyArrayAdapter(cube.data)) + expected = cube.data ** self.exponent + exponentiate(cube, self.exponent, in_place=True) + self.assertTrue(cube.has_lazy_data()) + self.assertArrayAlmostEqual(cube.data, expected) + + def test_exponentiate__preloaded_data__not_inplace(self): + # Confirm that the cube's data is lazy after an operation that is not + # in-place and after pre-loading the data. + cube = self.cube.copy() + cube.lazy_data(array=NumpyArrayAdapter(cube.data)) + expected = cube.data ** self.exponent + result = exponentiate(cube, self.exponent, in_place=False) + self.assertTrue(result.has_lazy_data()) + self.assertArrayAlmostEqual(result.data, expected) + + +if __name__ == "__main__": + tests.main()