Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/iris/analysis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down
48 changes: 46 additions & 2 deletions lib/iris/tests/test_analysis.py
Original file line number Diff line number Diff line change
@@ -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.
#
Expand Down Expand Up @@ -411,17 +411,20 @@ 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)

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()
Expand All @@ -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(
Expand All @@ -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.],
Expand Down Expand Up @@ -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],
Expand All @@ -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.],
Expand All @@ -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.'

Expand Down