def setUp(self): """Set up a UK deterministic cube for testing.""" self.cycletime = datetime.datetime(2017, 1, 10, 6, 0) cube_uk_det = set_up_variable_cube(np.full((4, 4), 273.15, dtype=np.float32), time=self.cycletime, frt=datetime.datetime( 2017, 1, 10, 3, 0)) cube_uk_det.remove_coord("forecast_period") # set up forecast periods of 6, 8 and 10 hours time_points = [1484038800, 1484046000, 1484053200] cube_uk_det = add_coordinate( cube_uk_det, time_points, "time", dtype=np.int64, coord_units="seconds since 1970-01-01 00:00:00") fp_coord = forecast_period_coord(cube_uk_det) cube_uk_det.add_aux_coord(fp_coord, data_dims=0) self.cube_uk_det = add_coordinate(cube_uk_det, [1000], "model_id") self.cube_uk_det.add_aux_coord( iris.coords.AuxCoord(["uk_det"], long_name="model_configuration"))
def test_unmatched_realizations(self): """Test error if realizations on temperature and lapse rate do not match""" temp_3d = add_coordinate(self.temperature, [0, 1, 2], 'realization') lrt_3d = add_coordinate(self.lapse_rate, [2, 3, 4], 'realization') msg = 'Lapse rate cube coordinate "realization" does not match ' with self.assertRaisesRegex(ValueError, msg): _ = apply_gridded_lapse_rate(temp_3d, lrt_3d, self.source_orog, self.dest_orog)
def test_realizations(self): """Test processing of a cube with multiple realizations""" temp_3d = add_coordinate(self.temperature, [0, 1, 2], 'realization') lrt_3d = add_coordinate(self.lapse_rate, [0, 1, 2], 'realization') result = apply_gridded_lapse_rate(temp_3d, lrt_3d, self.source_orog, self.dest_orog) self.assertArrayEqual( result.coord('realization').points, np.array([0, 1, 2])) for subcube in result.slices_over('realization'): self.assertArrayAlmostEqual(subcube.data, self.expected_data)
def set_up_basic_model_config_cube(frt=None, time_points=None): """Set up cube with dimensions of time x air_temperature x lat x lon, plus model id and configuration scalar coordinates Args: frt (datetime.datetime): Forecast reference time point time_points (list): List of times as datetime instances to create a dim coord """ if frt is None: frt = dt(2017, 1, 10, 3, 0) if time_points is None: time_points = [dt(2017, 1, 10, 9, 0), dt(2017, 1, 10, 10, 0), dt(2017, 1, 10, 11, 0)] model_id_coord = AuxCoord([1000], long_name="model_id") model_config_coord = AuxCoord(["uk_det"], long_name="model_configuration") data = np.ones((2, 2, 2), dtype=np.float32) thresholds = np.array([275., 276.], dtype=np.float32) cube = set_up_probability_cube( data, thresholds, time=frt, frt=frt, include_scalar_coords=[model_id_coord, model_config_coord]) cube = add_coordinate( cube, time_points, "time", is_datetime=True) return cube
def setUp(self): """Set up plugin with suitable parameters (used for dict only)""" self.plugin = ChooseWeightsLinear( "forecast_period", CONFIG_DICT_UKV) # create a cube with unnecessary realization coordinate (dimensions: # model_id: 2; realization: 1; latitude: 2; longitude: 2) cube = set_up_variable_cube(278.*np.ones((1, 2, 2), dtype=np.float32)) self.cube = add_coordinate( cube, [1000, 2000], "model_id", dtype=np.int32) self.cube.add_aux_coord( AuxCoord(["uk_det", "uk_ens"], long_name="model_configuration"), data_dims=0) # create a reference cube as above WITHOUT realization new_data = self.cube.data[:, 0, :, :] dim_coords = [(self.cube.coord("model_id"), 0), (self.cube.coord("latitude"), 1), (self.cube.coord("longitude"), 2)] aux_coords = [(self.cube.coord("model_configuration"), 0), (self.cube.coord("time"), None), (self.cube.coord("forecast_period"), None), (self.cube.coord("forecast_reference_time"), None)] self.reference_cube = iris.cube.Cube( new_data, "air_temperature", units="K", dim_coords_and_dims=dim_coords, aux_coords_and_dims=aux_coords) self.reference_cube.add_aux_coord(AuxCoord(0, "realization")) # split into a cubelist for each model self.reference_cubelist = iris.cube.CubeList([self.reference_cube[0], self.reference_cube[1]])
def set_up_basic_model_config_cube(frt=None, time_points=None): """Set up cube with dimensions of realization x time x lat x lon, plus model id and configuration scalar coords Kwargs: frt (datetime): Forecast reference time point time_points (list): List of times as datetime instances to create a dim coord """ if frt is None: frt = dt(2017, 1, 10, 3, 0) if time_points is None: time_points = [dt(2017, 1, 10, 9, 0), dt(2017, 1, 10, 10, 0), dt(2017, 1, 10, 11, 0)] model_id_coord = AuxCoord([1000], long_name="model_id") model_config_coord = AuxCoord(["uk_det"], long_name="model_configuration") data = np.full((1, 2, 2), 275.15, dtype=np.float32) cube = set_up_variable_cube( data, time=frt, frt=frt, include_scalar_coords=[model_id_coord, model_config_coord]) cube = add_coordinate( cube, time_points, "time", is_datetime=True, order=[1, 0, 2, 3]) return cube
def create_cube_with_threshold(data=None, threshold_values=None): """ Create a cube with threshold coord. Data and threshold values MUST be provided as float32 (not float64), or cube setup will fail. """ if threshold_values is None: threshold_values = np.array([1.0], dtype=np.float32) if data is None: data = np.zeros((len(threshold_values), 2, 2, 2), dtype=np.float32) data[:, 0, :, :] = 0.5 data[:, 1, :, :] = 0.6 cube = set_up_probability_cube( data[:, 0, :, :], threshold_values, variable_name="rainfall_rate", threshold_units="m s-1", time=dt(2015, 11, 19, 1, 30), frt=dt(2015, 11, 18, 22, 0)) time_points = [dt(2015, 11, 19, 0, 30), dt(2015, 11, 19, 1, 30)] cube = add_coordinate( cube, time_points, "time", order=[1, 0, 2, 3], is_datetime=True) cube.attributes["attribute_to_update"] = "first_value" cube.data = data return cube
def setUp(self): """Create a cube with threshold coord is not first coord.""" self.cube1 = create_cube_with_threshold() self.cube2 = add_coordinate( self.cube1, np.arange(2).astype(np.float32), "realization", dtype=np.float32) self.coord_name = find_threshold_coordinate(self.cube1).name()
def test_height_and_realization_dict(self): """Test blending members with a configuration dictionary.""" cube = set_up_variable_cube(274.*np.ones((2, 2, 2), dtype=np.float32)) cube = add_coordinate(cube, [10., 20.], "height", coord_units="m") cubes = iris.cube.CubeList([]) for cube_slice in cube.slices_over("realization"): cubes.append(cube_slice) expected_weights = np.array([[1., 0.5], [0., 0.5]]) config_dict = {0: {"height": [15, 25], "weights": [1, 0], "units": "m"}, 1: {"height": [15, 25], "weights": [0, 1], "units": "m"}} plugin = ChooseWeightsLinear( "height", config_dict, config_coord_name="realization") result = plugin.process(cubes) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayAlmostEqual(result.data, expected_weights) self.assertAlmostEqual(result.name(), "weights") expected_coords = { 'time', 'forecast_reference_time', 'forecast_period', 'height', 'realization'} result_coords = {coord.name() for coord in result.coords()} self.assertSetEqual(result_coords, expected_coords)
def test_missing_coord(self): """Test error if temperature cube has realizations but lapse rate does not""" temp_3d = add_coordinate(self.temperature, [0, 1, 2], 'realization') msg = 'Lapse rate cube has no coordinate "realization"' with self.assertRaisesRegex(ValueError, msg): _ = apply_gridded_lapse_rate(temp_3d, self.lapse_rate, self.source_orog, self.dest_orog)
def test_datatype(self): """Test coordinate datatype""" result = add_coordinate(self.input_cube, self.height_points, 'height', coord_units=self.height_unit, dtype=np.int32) self.assertEqual(result.coord('height').dtype, np.int32)
def test_reorder(self): """Test new coordinate can be placed in different positions""" input_cube = set_up_variable_cube(np.ones((4, 3, 4), dtype=np.float32)) result = add_coordinate( input_cube, self.height_points, 'height', coord_units=self.height_unit, order=[1, 0, 2, 3]) self.assertSequenceEqual(result.shape, (4, 10, 3, 4)) self.assertEqual(result.coord_dims('height'), (1,))
def setUp(self): """Set up test cube and coordinate""" cube = set_up_variable_cube( np.zeros((2, 2), dtype=np.float32), name="lwe_thickness_of_precipitation_amount", units="m", time=dt(2017, 1, 10, 5, 0), frt=dt(2017, 1, 10, 3, 0)) self.cube = add_coordinate( cube, [dt(2017, 1, 10, 5, 0), dt(2017, 1, 10, 6, 0)], "time", is_datetime=True) self.coord_name = "time"
def test_larger_num(self): """Test it works with larger num_of_vals. """ plugin = NonLinearWeights(cval=0.5) cubenew = add_coordinate( self.cube, np.arange(6), 'realization', dtype=np.int32) coord_name = 'realization' result = plugin.process(cubenew, coord_name) expected_result = np.array([0.50793651, 0.25396825, 0.12698413, 0.06349206, 0.03174603, 0.01587302]) self.assertArrayAlmostEqual(result.data, expected_result)
def test_fails_weights_negative(self): """Test it raises a Value Error if weights become negative. """ plugin = LinearWeights(y0val=10.0, slope=-5.0) cubenew = add_coordinate(self.cube, np.arange(6), "realization", dtype=np.int32) coord = cubenew.coord('realization') msg = 'Weights must be positive' with self.assertRaisesRegex(ValueError, msg): plugin.process(cubenew, coord)
def test_ordering_for_realization_threshold_percentile_over_coordinate( self): """Test that the cube has been reordered, if it is originally in an undesirable order and the cube contains a "threshold" coordinate, a "realization" coordinate and a "percentile_over" coordinate.""" cube = set_up_probability_cube( np.zeros((3, 4, 5), dtype=np.float32), np.array([273., 274., 275.], dtype=np.float32)) cube = add_coordinate(cube, [0, 1, 2], "realization") cube = add_coordinate(cube, [10, 50, 90], "percentile_over_neighbourhood") cube.transpose([4, 3, 2, 1, 0]) save_netcdf(cube, self.filepath) result = load_cube(self.filepath) self.assertEqual(result.coord_dims("realization")[0], 0) self.assertEqual( result.coord_dims("percentile_over_neighbourhood")[0], 1) self.assertEqual(result.coord_dims("threshold")[0], 2) self.assertArrayAlmostEqual(result.coord_dims("latitude")[0], 3) self.assertArrayAlmostEqual(result.coord_dims("longitude")[0], 4)
def setUp(self): """Set up temperature, pressure, and relative humidity cubes that contain multiple height levels; in this case the values of these diagnostics are identical on each level.""" super().setUp() self.height_points = np.array([5., 10., 20.]) height_attribute = {"positive": "up"} self.temperature_cube = add_coordinate( self.temperature, self.height_points, 'height', coord_units='m', attributes=height_attribute) self.relative_humidity_cube = add_coordinate( self.relative_humidity, self.height_points, 'height', coord_units='m', attributes=height_attribute) self.pressure_cube = add_coordinate( self.pressure, self.height_points, 'height', coord_units='m', attributes=height_attribute)
def test_datetime_no_fp(self): """Test a leading time coordinate can be added successfully when there is no forecast period on the input cube""" self.input_cube.remove_coord("forecast_period") datetime_points = [ datetime(2017, 10, 10, 3, 0), datetime(2017, 10, 10, 4, 0)] result = add_coordinate( self.input_cube, datetime_points, "time", is_datetime=True) # check a forecast period coordinate has been added expected_fp_points = 3600*np.array([6, 7], dtype=np.int64) self.assertArrayAlmostEqual( result.coord("forecast_period").points, expected_fp_points)
def test_basic(self): """Test addition of a leading height coordinate""" result = add_coordinate( self.input_cube, self.height_points, 'height', coord_units=self.height_unit) self.assertIsInstance(result, iris.cube.Cube) self.assertSequenceEqual(result.shape, (10, 3, 4)) self.assertEqual(result.coord_dims('height'), (0,)) self.assertArrayAlmostEqual( result.coord('height').points, self.height_points) self.assertEqual(result.coord('height').dtype, np.float32) self.assertEqual(result.coord('height').units, self.height_unit)
def setUp(self): """Set up a cube for the tests.""" cube = set_up_variable_cube( np.ones((1, 7, 7), dtype=np.float32), time=datetime.datetime(2015, 11, 23, 7, 0), frt=datetime.datetime(2015, 11, 23, 3, 0)) cube.remove_coord("forecast_period") time_points = [1448262000, 1448265600] self.cube = add_coordinate( cube, time_points, "time", dtype=np.int64, coord_units="seconds since 1970-01-01 00:00:00", order=[1, 0, 2, 3])
def setUp(self): """Set up test cubes""" cube = set_up_variable_cube( np.ones((12, 12), dtype=np.float32), time=datetime.datetime(2017, 2, 17, 6, 0), frt=datetime.datetime(2017, 2, 17, 6, 0)) cube.remove_coord("forecast_period") self.time_points = np.arange( 1487311200, 1487354400, 3600).astype(np.int64) self.cube = add_coordinate( cube, self.time_points, "time", dtype=np.int64, coord_units="seconds since 1970-01-01 00:00:00")
def test_works_with_larger_num(self): """Test it works with larger num_of_vals. """ plugin = LinearWeights(y0val=10.0, ynval=5.0) cubenew = add_coordinate(self.cube, np.arange(6), "realization", dtype=np.int32) coord = cubenew.coord('realization') result = plugin.process(cubenew, coord) expected_result = np.array( [0.22222222, 0.2, 0.17777778, 0.15555556, 0.13333333, 0.11111111]) self.assertArrayAlmostEqual(result.data, expected_result)
def test_adding_coordinate_with_attribute(self): """Test addition of a leading height coordinate with an appropriate attribute.""" height_attribute = {"positive": "up"} result = add_coordinate(self.input_cube, self.height_points, 'height', coord_units=self.height_unit, attributes=height_attribute) self.assertIsInstance(result, iris.cube.Cube) self.assertEqual(result.coord_dims('height'), (0, )) self.assertEqual(result.coord('height').attributes, height_attribute)
def test_datetime(self): """Test a leading time coordinate can be added successfully""" datetime_points = [ datetime(2017, 10, 10, 3, 0), datetime(2017, 10, 10, 4, 0)] result = add_coordinate( self.input_cube, datetime_points, "time", is_datetime=True) # check time is now the leading dimension self.assertEqual(result.coord_dims("time"), (0,)) self.assertEqual(len(result.coord("time").points), 2) # check forecast period has been updated expected_fp_points = 3600*np.array([6, 7], dtype=np.int64) self.assertArrayAlmostEqual( result.coord("forecast_period").points, expected_fp_points)
def test_works_with_missing_coord(self): """Test it works with missing coord """ plugin = LinearWeights(y0val=10.0, ynval=5.0) cubenew = add_coordinate(self.cube, np.arange(6), "realization", dtype=np.int32) coord_vals = '0, 1, 2, 3, 4, 5, 6' coord_name = 'realization' result = plugin.process(cubenew, coord_name, coord_vals) expected_result = np.array( [0.206349, 0.190476, 0.174603, 0.15873, 0.142857, 0.126984]) self.assertArrayAlmostEqual(result.data, expected_result)
def setUp(self): """Set up the test inputs.""" time_start = datetime.datetime(2017, 11, 1, 3) time_mid = datetime.datetime(2017, 11, 1, 6) time_end = datetime.datetime(2017, 11, 1, 9) self.npoints = 3 data_time_0 = np.ones((self.npoints, self.npoints), dtype=np.float32) cube_time_0 = set_up_variable_cube(data_time_0, time=time_start, frt=time_start) self.cube = add_coordinate(cube_time_0, [time_start, time_mid, time_end], 'time', is_datetime=True) cube_time_0_equalarea = set_up_variable_cube(data_time_0, time=time_start, frt=time_start, spatial_grid='equalarea') self.cube_equalarea = add_coordinate(cube_time_0_equalarea, [time_start, time_mid, time_end], 'time', is_datetime=True)
def test_works_with_missing_coord(self): """Test it works with missing coord """ plugin = NonLinearWeights(cval=0.6) cubenew = add_coordinate(self.cube, np.arange(6), 'realization', dtype=np.int32) coord_vals = '0, 1, 2, 3, 4, 5, 6' coord_name = 'realization' result = plugin.process(cubenew, coord_name, coord_vals) expected_result = np.array( [0.41472, 0.250112, 0.151347, 0.092088, 0.056533, 0.0352]) self.assertArrayAlmostEqual(result.data, expected_result)
def setUp(self): """Setup for testing process coord""" cube = set_up_variable_cube( np.ones((2, 2), dtype=np.float32), name="lwe_thickness_of_precipitation_amount", units="m", time=dt(2017, 1, 10, 5, 0), frt=dt(2017, 1, 10, 3, 0)) self.cube = add_coordinate( cube, [dt(2017, 1, 10, 5, 0), dt(2017, 1, 10, 6, 0)], "time", is_datetime=True) self.cube.data[1, :] = [[2, 2], [2, 2]] self.cube_coord = self.cube.coord("time") self.coordinate = self.cube_coord.name() self.exp_coord_vals = ','.join( [str(x) for x in self.cube_coord.points]) self.wrong_coord_vals = ','.join(['1484020800', self.exp_coord_vals])
def setUp(self): """Set up for testing process method""" cube = set_up_variable_cube( np.zeros((2, 2), dtype=np.float32), name="lwe_thickness_of_precipitation_amount", units="m", time=dt(2017, 1, 10, 5, 0), frt=dt(2017, 1, 10, 3, 0)) self.cube = add_coordinate( cube, [dt(2017, 1, 10, 5, 0), dt(2017, 1, 10, 6, 0)], "time", is_datetime=True) self.coord_name = "time" self.coord_vals = ','.join( [str(x) for x in self.cube.coord("time").points])
def setUp(self): """Set up a test cube with several time points""" cube = set_up_variable_cube( np.ones((12, 12), dtype=np.float32), time=datetime.datetime(2017, 2, 17, 6, 0), frt=datetime.datetime(2017, 2, 17, 6, 0)) cube.remove_coord("forecast_period") self.time_points = np.arange( 1487311200, 1487354400, 3600).astype(np.int64) self.cube = add_coordinate( cube, self.time_points, "time", dtype=np.int64, coord_units="seconds since 1970-01-01 00:00:00") self.time_dt = datetime.datetime(2017, 2, 17, 6, 0) self.time_constraint = iris.Constraint( time=lambda cell: cell.point == PartialDateTime( self.time_dt.year, self.time_dt.month, self.time_dt.day, self.time_dt.hour))