diff --git a/lib/iris/analysis/trajectory.py b/lib/iris/analysis/trajectory.py index c5433c91fc..b8a8707d58 100644 --- a/lib/iris/analysis/trajectory.py +++ b/lib/iris/analysis/trajectory.py @@ -342,8 +342,6 @@ def interpolate(cube, sample_points, method=None): # This is **not** proper mask handling, because we cannot produce a # masked result, but it ensures we use a "filled" version of the # input in this case. - if cube.fill_value is not None: - source_data.fill_value = cube.fill_value source_data = source_data.filled() new_cube.data[:] = source_data # NOTE: we assign to "new_cube.data[:]" and *not* just "new_cube.data", diff --git a/lib/iris/fileformats/pp.py b/lib/iris/fileformats/pp.py index a046f709c2..9b493346f6 100644 --- a/lib/iris/fileformats/pp.py +++ b/lib/iris/fileformats/pp.py @@ -976,9 +976,8 @@ def _data_bytes_to_shaped_array(data_bytes, lbpack, boundary_packing, # condition" array, which is split into 4 quartiles, North # East, South, West and where North and South contain the corners. compressed_data = data - if data_type.kind != 'i': - data_type = np.dtype('f8') - data = np.full(data_shape, np.nan, dtype=data_type) + data = np.ma.masked_all(data_shape) + data.fill_value = mdi boundary_height = boundary_packing.y_halo + boundary_packing.rim_width boundary_width = boundary_packing.x_halo + boundary_packing.rim_width @@ -1019,9 +1018,8 @@ def _data_bytes_to_shaped_array(data_bytes, lbpack, boundary_packing, 'Could not load.') land_mask = mask.data.astype(np.bool) sea_mask = ~land_mask - if data_type.kind != 'i': - data_type = np.dtype('f8') - new_data = np.full(land_mask.shape, np.nan, dtype=data_type) + new_data = np.ma.masked_all(land_mask.shape) + new_data.fill_value = mdi if lbpack.n3 == 1: # Land mask packed data. # Sometimes the data comes in longer than it should be (i.e. it diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py index aa982cd105..b2befe26f6 100644 --- a/lib/iris/tests/__init__.py +++ b/lib/iris/tests/__init__.py @@ -1156,16 +1156,6 @@ class MyPlotTests(test.GraphicsTest): return skip(fn) -# Control for @skip_dask_mask : Set to False to run the dask mask failing -# tests. -_SKIP_DASK_MASK_TESTS = True - - -skip_dask_mask = unittest.skipIf(_SKIP_DASK_MASK_TESTS, - 'Test(s) currently fail on Dask Mask Array ' - 'feature branch.') - - skip_grib = unittest.skipIf(not GRIB_AVAILABLE, 'Test(s) require "gribapi", ' 'which is not available.') diff --git a/lib/iris/tests/integration/test_ff.py b/lib/iris/tests/integration/test_ff.py index fa28d9ae72..467265e8b3 100644 --- a/lib/iris/tests/integration/test_ff.py +++ b/lib/iris/tests/integration/test_ff.py @@ -80,7 +80,6 @@ def test_cube_data(self): [4.626897, 6.520156]]), atol=1.0e-6) - @tests.skip_dask_mask def test_cube_mask(self): # Check the data mask : should be just the centre 6x2 section. cube = self.test_cube diff --git a/lib/iris/tests/integration/test_trajectory.py b/lib/iris/tests/integration/test_trajectory.py index 87784cce8a..c4945333ed 100644 --- a/lib/iris/tests/integration/test_trajectory.py +++ b/lib/iris/tests/integration/test_trajectory.py @@ -172,7 +172,6 @@ def setUp(self): self.sample_points = [('longitude', longitudes), ('latitude', latitudes)] - @tests.skip_dask_mask def test_tri_polar(self): # extract sampled_cube = traj_interpolate(self.cube, self.sample_points) @@ -204,7 +203,7 @@ def test_tri_polar__nearest(self): # TODO: arguably, we should support masked data properly in the # interpolation routine. In the legacy code, that is unfortunately # just not the case. - test_cube.fill_value = 0 + test_cube.data.fill_value = 0 # Test points on a regular global grid, with unrelated steps + offsets # and an extended range of longitude values. diff --git a/lib/iris/tests/unit/fileformats/grib/save_rules/test_data_section.py b/lib/iris/tests/unit/fileformats/grib/save_rules/test_data_section.py index 9382429a5f..e44e038789 100644 --- a/lib/iris/tests/unit/fileformats/grib/save_rules/test_data_section.py +++ b/lib/iris/tests/unit/fileformats/grib/save_rules/test_data_section.py @@ -93,11 +93,10 @@ def test_simple(self): # Check the correct data values have been set. self.assertValues(grib_api, np.arange(5)) - @tests.skip_dask_mask def test_masked_with_finite_fill_value(self): cube = iris.cube.Cube(np.ma.MaskedArray([1.0, 2.0, 3.0, 1.0, 2.0, 3.0], - mask=[0, 0, 0, 1, 1, 1]), - fill_value=2000) + mask=[0, 0, 0, 1, 1, 1], + fill_value=2000)) grib_message = mock.sentinel.GRIB_MESSAGE with mock.patch(GRIB_API) as grib_api: data_section(cube, grib_message) @@ -107,11 +106,10 @@ def test_masked_with_finite_fill_value(self): # Check the correct data values have been set. self.assertValues(grib_api, [1, 2, 3, FILL, FILL, FILL]) - @tests.skip_dask_mask def test_masked_with_nan_fill_value(self): cube = iris.cube.Cube(np.ma.MaskedArray([1.0, 2.0, 3.0, 1.0, 2.0, 3.0], - mask=[0, 0, 0, 1, 1, 1]), - fill_value=np.nan) + mask=[0, 0, 0, 1, 1, 1], + fill_value=np.nan)) grib_message = mock.sentinel.GRIB_MESSAGE with mock.patch(GRIB_API) as grib_api: data_section(cube, grib_message) @@ -134,14 +132,13 @@ def test_scaled(self): # Check the correct data values have been set. self.assertValues(grib_api, np.arange(5) * 1000) - @tests.skip_dask_mask def test_scaled_with_finite_fill_value(self): # When re-scaling masked data with a finite fill value, ensure # the fill value and any filled values are also re-scaled. cube = iris.cube.Cube(np.ma.MaskedArray([1.0, 2.0, 3.0, 1.0, 2.0, 3.0], - mask=[0, 0, 0, 1, 1, 1]), - standard_name='geopotential_height', units='km', - fill_value=2000) + mask=[0, 0, 0, 1, 1, 1], + fill_value=2000), + standard_name='geopotential_height', units='km') grib_message = mock.sentinel.GRIB_MESSAGE with mock.patch(GRIB_API) as grib_api: data_section(cube, grib_message) @@ -151,15 +148,14 @@ def test_scaled_with_finite_fill_value(self): # Check the correct data values have been set. self.assertValues(grib_api, [1000, 2000, 3000, FILL, FILL, FILL]) - @tests.skip_dask_mask def test_scaled_with_nan_fill_value(self): # When re-scaling masked data with a NaN fill value, ensure # a fill value is chosen which allows for the scaling, and any # filled values match the chosen fill value. cube = iris.cube.Cube(np.ma.MaskedArray([-1.0, 2.0, -1.0, 2.0], - mask=[0, 0, 1, 1]), - standard_name='geopotential_height', units='km', - fill_value=np.nan) + mask=[0, 0, 1, 1], + fill_value=np.nan), + standard_name='geopotential_height', units='km') grib_message = mock.sentinel.GRIB_MESSAGE with mock.patch(GRIB_API) as grib_api: data_section(cube, grib_message) diff --git a/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py b/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py index 8d4bf71414..1e38baac86 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py +++ b/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py @@ -32,84 +32,6 @@ from iris.tests import mock -@tests.skip_dask_mask -class TestFillValue(tests.IrisTest): - def setUp(self): - name = 'iris.fileformats.netcdf._assert_case_specific_facts' - patch = mock.patch(name) - patch.start() - self.addCleanup(patch.stop) - - self.engine = mock.Mock() - self.cf = None - self.filename = 'DUMMY' - - def _make_cf_var(self, dtype): - variable = mock.Mock(spec=netCDF4.Variable, - dtype=dtype) - cf_var = mock.MagicMock(spec=iris.fileformats.cf.CFVariable, - cf_data=variable, - cf_name='DUMMY_VAR', - cf_group=mock.Mock(), - dtype=dtype, - shape=(1,)) - return cf_var - - def _test(self, cf_var, expected_fill_value): - cube = _load_cube(self.engine, self.cf, cf_var, self.filename) - self.assertEqual(cube.fill_value, expected_fill_value) - - def test_from_attribute_dtype_f4(self): - # A _FillValue attribute on the netCDF variable should end up as - # the fill_value for the cube. - dtype = np.dtype('f4') - fill_value = 9999. - cf_var = self._make_cf_var(dtype) - cf_var.cf_data._FillValue = fill_value - self._test(cf_var, fill_value) - - def test_from_default_dtype_f4(self): - # Without an explicit _FillValue attribute on the netCDF - # variable, the fill value should be set to `None`. - dtype = np.dtype('f4') - cf_var = self._make_cf_var(dtype) - self._test(cf_var, None) - - def test_from_attribute_dtype_i4(self): - # A _FillValue attribute on the netCDF variable should end up as - # the fill_value for the cube. - dtype = np.dtype('i4') - fill_value = 9999 - cf_var = self._make_cf_var(dtype) - cf_var.cf_data._FillValue = fill_value - self._test(cf_var, fill_value) - - def test_from_default_dtype_i4(self): - # Without an explicit _FillValue attribute on the netCDF - # variable, the fill value should be set to `None`. - dtype = np.dtype('i4') - cf_var = self._make_cf_var(dtype) - self._test(cf_var, None) - - def test_from_attribute_with_scale_offset(self): - # The _FillValue attribute still takes priority even when an - # offset/scale transformation takes place on the data. - dtype = np.dtype('i2') - fill_value = 999 - cf_var = self._make_cf_var(dtype) - cf_var.scale_factor = np.float64(1.5) - cf_var.cf_data._FillValue = fill_value - self._test(cf_var, fill_value) - - def test_from_default_with_scale_offset(self): - # Without an explicit _FillValue attribute on the netCDF - # variable, the fill value should be set to `None`. - dtype = np.dtype('i2') - cf_var = self._make_cf_var(dtype) - cf_var.scale_factor = np.float64(1.5) - self._test(cf_var, None) - - class TestCoordAttributes(tests.IrisTest): @staticmethod def _patcher(engine, cf, cf_group):