diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py index 9613550929..30f13a9aa3 100644 --- a/lib/iris/analysis/__init__.py +++ b/lib/iris/analysis/__init__.py @@ -1080,7 +1080,7 @@ def _percentile(data, axis, percent, fast_percentile_method=False, # Perform the percentile calculation. if fast_percentile_method: msg = 'Cannot use fast np.percentile method with masked array.' - if ma.isMaskedArray(data): + if ma.is_masked(data): raise TypeError(msg) result = np.percentile(data, percent, axis=-1) result = result.T @@ -1090,6 +1090,8 @@ def _percentile(data, axis, percent, fast_percentile_method=False, **kwargs) if not ma.isMaskedArray(data) and not ma.is_masked(result): result = np.asarray(result) + else: + result = ma.MaskedArray(result) # Ensure to unflatten any leading dimensions. if shape: diff --git a/lib/iris/tests/test_analysis.py b/lib/iris/tests/test_analysis.py index e07848a3d8..b44bb39408 100644 --- a/lib/iris/tests/test_analysis.py +++ b/lib/iris/tests/test_analysis.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2018, Met Office +# (C) British Crown Copyright 2010 - 2019, Met Office # # This file is part of Iris. # @@ -411,10 +411,12 @@ class TestAggregators(tests.IrisTest): def _check_collapsed_percentile(self, cube, percents, collapse_coord, expected_result, CML_filename=None, **kwargs): + cube_data_type = type(cube.data) expected_result = np.array(expected_result, dtype=np.float32) result = cube.collapsed(collapse_coord, iris.analysis.PERCENTILE, percent=percents, **kwargs) np.testing.assert_array_almost_equal(result.data, expected_result) + self.assertEqual(type(result.data), cube_data_type) if CML_filename is not None: self.assertCML(result, ('analysis', CML_filename), checksum=False) @@ -422,6 +424,7 @@ def _check_percentile(self, data, axis, percents, expected_result, **kwargs): result = iris.analysis._percentile(data, axis, percents, **kwargs) np.testing.assert_array_almost_equal(result, expected_result) + self.assertEqual(type(result), type(expected_result)) def test_percentile_1d_25_percent(self): cube = tests.stock.simple_1d() @@ -445,6 +448,13 @@ def test_fast_percentile_1d_75_percent(self): cube, 75, 'foo', 7.5, fast_percentile_method=True, CML_filename='third_quartile_foo_1d_fast_percentile.cml') + def test_fast_percentile_1d_75_percent_masked_type_no_mask(self): + cube = tests.stock.simple_1d() + cube.data = ma.MaskedArray(cube.data) + self._check_collapsed_percentile( + cube, 75, 'foo', 7.5, fast_percentile_method=True, + CML_filename='third_quartile_foo_1d_fast_percentile.cml') + def test_percentile_2d_single_coord(self): cube = tests.stock.simple_2d() self._check_collapsed_percentile( @@ -469,6 +479,20 @@ def test_fast_percentile_2d_two_coords(self): cube, 25, ['foo', 'bar'], [2.75], fast_percentile_method=True, CML_filename='first_quartile_foo_bar_2d_fast_percentile.cml') + def test_fast_percentile_2d_single_coord_masked_type_no_mask(self): + cube = tests.stock.simple_2d() + cube.data = ma.MaskedArray(cube.data) + self._check_collapsed_percentile( + cube, 25, 'foo', [0.75, 4.75, 8.75], fast_percentile_method=True, + CML_filename='first_quartile_foo_2d_fast_percentile.cml') + + def test_fast_percentile_2d_two_coords_masked_type_no_mask(self): + cube = tests.stock.simple_2d() + cube.data = ma.MaskedArray(cube.data) + self._check_collapsed_percentile( + cube, 25, ['foo', 'bar'], [2.75], fast_percentile_method=True, + CML_filename='first_quartile_foo_bar_2d_fast_percentile.cml') + def test_percentile_3d(self): array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) expected_result = np.array([[6., 7., 8., 9.], @@ -503,6 +527,16 @@ def test_fast_percentile_3d_axis_one(self): self._check_percentile(array_3d, 1, 50, expected_result, fast_percentile_method=True) + def test_fast_percentile_3d_axis_one_masked_type_no_mask(self): + array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) + array_3d = np.ma.MaskedArray(array_3d) + expected_result = ma.MaskedArray([[4., 5., 6., 7.], + [16., 17., 18., 19.]], + dtype=np.float32) + + self._check_percentile(array_3d, 1, 50, expected_result, + fast_percentile_method=True) + def test_percentile_3d_axis_two(self): array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) expected_result = np.array([[1.5, 5.5, 9.5], @@ -520,6 +554,16 @@ def test_fast_percentile_3d_axis_two(self): self._check_percentile(array_3d, 2, 50, expected_result, fast_percentile_method=True) + def test_fast_percentile_3d_axis_two_masked_type_no_mask(self): + array_3d = np.arange(24, dtype=np.int32).reshape((2, 3, 4)) + array_3d = ma.MaskedArray(array_3d) + expected_result = ma.MaskedArray([[1.5, 5.5, 9.5], + [13.5, 17.5, 21.5]], + dtype=np.float32) + + self._check_percentile(array_3d, 2, 50, expected_result, + fast_percentile_method=True) + def test_percentile_3d_masked(self): cube = tests.stock.simple_3d_mask() expected_result = [[12., 13., 14., 15.], @@ -530,7 +574,7 @@ def test_percentile_3d_masked(self): cube, 75, 'wibble', expected_result, CML_filename='last_quartile_foo_3d_masked.cml') - def test_fast_percentile_3d_masked(self): + def test_fast_percentile_3d_masked_type_masked(self): cube = tests.stock.simple_3d_mask() msg = 'Cannot use fast np.percentile method with masked array.'