def missing_additional_data(self, method, ancillary_data, additional_data): """Test that the plugin copes with missing additional data.""" plugin = Plugin(method) with self.assertRaises(KeyError): plugin.process(self.cube, self.sites, self.neighbour_list, ancillary_data, additional_data)
def test_extracted_value_deep_valley(self): """Test that the plugin returns the correct value. Site set to be 100m or 70m below the land surface (90m or 60m below sea level). The enforcement of a maximum extrapolation down into valleys should result in the two site altitudes returning the same temperature. This is an extrapolation scenario, an 'unresolved valley'.""" # Temperatures set up to mimic a cold night with an inversion where # valley temperatures may be expected to fall considerably due to # katabatic drainage. t_level0 = np.ones((1, 20, 20)) * 0. t_level1 = np.ones((1, 20, 20)) * 1. t_level2 = np.ones((1, 20, 20)) * 2. t_data = np.vstack((t_level0, t_level1, t_level2)) t_data.resize((3, 20, 20)) self.ad['temperature_on_height_levels'].data = t_data cube = self.cube.extract(self.time_extract) cube.data = cube.data * 0.0 self.sites['100']['altitude'] = -90. self.neighbour_list['dz'] = -100. plugin = Plugin(self.method) result_dz = plugin.process(cube, self.sites, self.neighbour_list, self.ancillary_data, self.ad, **self.kwargs) self.sites['100']['altitude'] = -60. self.neighbour_list['dz'] = -70. result_70 = plugin.process(cube, self.sites, self.neighbour_list, self.ancillary_data, self.ad, **self.kwargs) self.assertEqual(result_dz.data, result_70.data)
def different_projection(self, method, ancillary_data, additional_data, expected, **kwargs): """Test that the plugin copes with non-lat/lon grids.""" src_crs = ccrs.PlateCarree() trg_crs = ccrs.TransverseMercator(central_latitude=0, central_longitude=0) trg_crs_iris = coord_systems.TransverseMercator(0, 0, 0, 0, 1.0) lons = [-50, 50] lats = [-25, 25] x, y = [], [] for lon, lat in zip(lons, lats): x_trg, y_trg = trg_crs.transform_point(lon, lat, src_crs) x.append(x_trg) y.append(y_trg) new_x = DimCoord(np.linspace(x[0], x[1], 20), standard_name='projection_x_coordinate', units='m', coord_system=trg_crs_iris) new_y = DimCoord(np.linspace(y[0], y[1], 20), standard_name='projection_y_coordinate', units='m', coord_system=trg_crs_iris) new_cube = Cube(np.zeros(400).reshape(20, 20), long_name="air_temperature", dim_coords_and_dims=[(new_y, 0), (new_x, 1)], units="K") cube = self.cube.copy() cube = cube.regrid(new_cube, iris.analysis.Nearest()) if ancillary_data is not None: ancillary_data['orography'] = ancillary_data['orography'].regrid( new_cube, iris.analysis.Nearest()) if additional_data is not None: for ad in additional_data.keys(): additional_data[ad] = additional_data[ad].regrid( new_cube, iris.analysis.Nearest()) # Define neighbours on this new projection self.neighbour_list['i'] = 11 self.neighbour_list['j'] = 11 plugin = Plugin(method) with iris.FUTURE.context(cell_datetime_objects=True): cube = cube.extract(self.time_extract) result = plugin.process(cube, self.sites, self.neighbour_list, ancillary_data, additional_data, **kwargs) self.assertEqual(cube.coord_system(), trg_crs_iris) self.assertAlmostEqual(result.data, expected) self.assertEqual(result.coord(axis='y').name(), 'latitude') self.assertEqual(result.coord(axis='x').name(), 'longitude') self.assertAlmostEqual(result.coord(axis='y').points, 4.74) self.assertAlmostEqual(result.coord(axis='x').points, 9.47)
def test_make_spotdata_cube(self): """Test the make_cube function.""" plugin = Plugin().make_cube data = np.array([123]) result = plugin(self.cube, data, self.sites) self.assertIsInstance(result, Cube) self.assertEqual(result.data, data) self.assertEqual(result.name(), 'air_temperature')
def return_type(self, method, ancillary_data, additional_data, **kwargs): """Test that the plugin returns an iris.cube.Cube.""" plugin = Plugin(method) cube = self.cube.extract(self.time_extract) result = plugin.process(cube, self.sites, self.neighbour_list, ancillary_data, additional_data, **kwargs) self.assertIsInstance(result, Cube)
def test_aux_coord_and_metadata(self): """Test that the plugin returns cubes with expected metadata and coordinates.""" plugin = Plugin().make_cube data = np.array([123]) result = plugin(self.cube, data, self.sites) self.assertEqual(result.coord('forecast_reference_time'), self.cube.coord('forecast_reference_time')) self.assertEqual(result.metadata, self.cube.metadata)
def test_missing_forecast_ref_time_in_source(self): """Ensure an error is raised if a source cube is missing a forecast reference time.""" plugin = Plugin().make_cube data = np.array([123]) self.cube.remove_coord('forecast_reference_time') msg = 'No forecast reference time found on source cube.' with self.assertRaisesRegexp(CoordinateNotFoundError, msg): plugin(self.cube, data, self.sites)
def extracted_value(self, method, ancillary_data, additional_data, expected, **kwargs): """Test that the plugin returns the correct value.""" plugin = Plugin(method) cube = self.cube.extract(self.time_extract) result = plugin.process(cube, self.sites, self.neighbour_list, ancillary_data, additional_data, **kwargs) self.assertArrayAlmostEqual(result.data, expected)
def extracted_value(self, method, ancillary_data, additional_data, expected, **kwargs): """Test that the plugin returns the correct value.""" plugin = Plugin(method) with iris.FUTURE.context(cell_datetime_objects=True): cube = self.cube.extract(self.time_extract) result = plugin.process(cube, self.sites, self.neighbour_list, ancillary_data, additional_data, **kwargs) self.assertAlmostEqual(result.data, expected)
def test_invalid_method(self): """Test that the plugin can handle an invalid method being passed in.""" plugin = Plugin('quantum_interpolation') msg = 'Unknown method' cube = self.cube.extract(self.time_extract) with self.assertRaisesRegex(AttributeError, msg): plugin.process(cube, self.sites, self.neighbour_list, {}, None, **self.kwargs)
def test_build_latitude_coordinate(self): """Test building a latitude coordinate.""" plugin = Plugin()._build_coordinate coord_system = iris.coord_systems.GeogCS(6371229.0) result = plugin(self.latitudes, 'latitude', units='degrees', coord_system=coord_system) self.assertArrayEqual(result.points, self.latitudes) self.assertEqual(result.name(), 'latitude') self.assertIsInstance(result, DimCoord) self.assertEqual(result.units, 'degrees')
def test_cube_reorder_realization(self): """Test reordering a cube with a realization coordinate to make it come first.""" plugin = Plugin().make_stat_coordinate_first cube = set_up_cube(zero_point_indices=((0, 0, 2, 2), (1, 0, 3, 3), (0, 1, 0, 0), (1, 1, 2, 1)), num_time_points=2, num_grid_points=5, num_realization_points=2) incorrect_cube = cube.copy() incorrect_cube.transpose([1, 2, 0, 3]) result = plugin(incorrect_cube) self.assertEqual(cube.coords()[0].name(), result.coords()[0].name()) self.assertEqual(cube.coords(), result.coords())
def test__build_coordinates(self): """ Test the _build_coordinates private function. """ plugin = Plugin()._build_coordinates points = np.array([0, 1, 2]) indices, latitude, longitude, altitude, utc_offset, wmo_site = (plugin( points, points, points, points[::-1], points)) self.assertArrayEqual(indices.points, points) self.assertArrayEqual(altitude.points, points) self.assertArrayEqual(utc_offset.points, points[::-1]) self.assertEqual(latitude.name(), 'latitude') self.assertEqual(longitude.name(), 'longitude') self.assertEqual(wmo_site.name(), 'wmo_site') self.assertIsInstance(indices, DimCoord) self.assertIsInstance(latitude, AuxCoord)
def different_projection(self, method, ancillary_data, additional_data, expected, **kwargs): """Test that the plugin copes with non-lat/lon grids.""" trg_crs = None src_crs = ccrs.PlateCarree() trg_crs = ccrs.LambertConformal(central_longitude=50, central_latitude=10) trg_crs_iris = coord_systems.LambertConformal(central_lon=50, central_lat=10) lons = self.cube.coord('longitude').points lats = self.cube.coord('latitude').points x, y = [], [] for lon, lat in zip(lons, lats): x_trg, y_trg = trg_crs.transform_point(lon, lat, src_crs) x.append(x_trg) y.append(y_trg) new_x = AuxCoord(x, standard_name='projection_x_coordinate', units='m', coord_system=trg_crs_iris) new_y = AuxCoord(y, standard_name='projection_y_coordinate', units='m', coord_system=trg_crs_iris) cube = Cube(self.cube.data, long_name="air_temperature", dim_coords_and_dims=[(self.cube.coord('time'), 0)], aux_coords_and_dims=[(new_y, 1), (new_x, 2)], units="K") plugin = Plugin(method) with iris.FUTURE.context(cell_datetime_objects=True): cube = cube.extract(self.time_extract) result = plugin.process(cube, self.sites, self.neighbour_list, ancillary_data, additional_data, **kwargs) self.assertEqual(cube.coord_system(), trg_crs_iris) self.assertAlmostEqual(result.data, expected) self.assertEqual(result.coord(axis='y').name(), 'latitude') self.assertEqual(result.coord(axis='x').name(), 'longitude') self.assertAlmostEqual(result.coord(axis='y').points, 4.74) self.assertAlmostEqual(result.coord(axis='x').points, 9.47)
def test_cube_reorder_percentile_and_realization(self): """Test reordering a cube with a percentile and a realization coordinate. Should produce a warning and promote the first statistical coordinate that is found.""" plugin = Plugin().make_stat_coordinate_first cube = set_up_cube(zero_point_indices=((0, 0, 2, 2), (1, 0, 3, 3), (0, 1, 0, 0), (1, 1, 2, 1)), num_time_points=2, num_grid_points=5, num_realization_points=2) realization = cube.coords()[0][0].copy() cube.coords()[0].rename('percentile_over_time') cube.add_aux_coord(realization) cube = iris.util.new_axis(cube, 'realization') incorrect_cube = cube.copy() incorrect_cube.transpose([2, 1, 0, 3, 4]) with warnings.catch_warnings(record=True) as w_messages: result = plugin(incorrect_cube) assert len(w_messages) == 1 assert issubclass(w_messages[0].category, UserWarning) assert "More than one statistical" in str(w_messages[0]) self.assertEqual(cube.coords()[0].name(), result.coords()[0].name())