def create_symbol_cube(self, cubes: Union[List[Cube], CubeList]) -> Cube: """ Create an empty weather symbol cube Args: cubes: List of input cubes used to generate weather symbols Returns: A cube with suitable metadata to describe the weather symbols that will fill it and data initiated with the value -1 to allow any unset points to be readily identified. """ threshold_coord = find_threshold_coordinate(self.template_cube) template_cube = next(self.template_cube.slices_over([threshold_coord ])).copy() # remove coordinates and bounds that do not apply to weather symbols template_cube.remove_coord(threshold_coord) mandatory_attributes = generate_mandatory_attributes(cubes) optional_attributes = weather_code_attributes() if self.model_id_attr: optional_attributes.update( update_model_id_attr_attribute(cubes, self.model_id_attr)) symbols = create_new_diagnostic_cube( "weather_code", "1", template_cube, mandatory_attributes, optional_attributes=optional_attributes, data=np.ma.masked_all_like(template_cube.data).astype(np.int32), ) return symbols
def _core_wxcube(time_points, num_grid_points): """ Set up a wxcube with unnamed spatial dimensions Args: time_points (numpy.ndarray): Array of time points num_grid_points (int): Side length of square spatial grid Returns: iris.cube.Cube: cube of weather codes set to 1 data shape (time_points, num_grid_points, num_grid_points) """ if time_points is None: time_points = np.array([datetime_to_numdateval()]) data = np.ones((len(time_points), num_grid_points, num_grid_points)) cube = Cube(data, long_name="weather_code", units="1", attributes=weather_code_attributes()) time_origin = "hours since 1970-01-01 00:00:00" calendar = "gregorian" tunit = Unit(time_origin, calendar) cube.add_dim_coord( DimCoord(time_points, standard_name="time", units=tunit), 0) return cube
def create_symbol_cube(cubes): """ Create an empty weather symbol cube Args: cubes (list or iris.cube.CubeList): List of input cubes used to generate weather symbols Returns: iris.cube.Cube: A cube with suitable metadata to describe the weather symbols that will fill it and data initiated with the value -1 to allow any unset points to be readily identified. """ threshold_coord = find_threshold_coordinate(cubes[0]) template_cube = next(cubes[0].slices_over([threshold_coord])).copy() # remove coordinates and bounds that do not apply to weather symbols template_cube.remove_coord(threshold_coord) for coord in template_cube.coords(): if coord.name() in ["forecast_period", "time"]: coord.bounds = None attributes = generate_mandatory_attributes(cubes) symbols = create_new_diagnostic_cube( "weather_code", "1", template_cube, attributes, optional_attributes=weather_code_attributes(), data=np.ma.masked_all_like(template_cube.data).astype(np.int32), ) return symbols
def create_symbol_cube(cubes): """ Create an empty weather symbol cube Args: cubes (list or iris.cube.CubeList): List of input cubes used to generate weather symbols Returns: iris.cube.Cube: A cube with suitable metadata to describe the weather symbols that will fill it """ threshold_coord = find_threshold_coordinate(cubes[0]) template_cube = next(cubes[0].slices_over([threshold_coord])).copy() # remove coordinates and bounds that do not apply to weather symbols template_cube.remove_coord(threshold_coord) for coord in template_cube.coords(): if coord.name() in ['forecast_period', 'time']: coord.bounds = None attributes = generate_mandatory_attributes(cubes) symbols = create_new_diagnostic_cube( "weather_code", "1", template_cube, attributes, optional_attributes=weather_code_attributes(), dtype=np.int32) return symbols
def test_metadata_saves(self): """Test that the metadata saves as NetCDF correctly.""" self.cube.attributes.update(weather_code_attributes()) save_netcdf(self.cube, self.nc_file) result = load_cube(self.nc_file) self.assertArrayEqual(result.attributes["weather_code"], self.wxcode) self.assertEqual(result.attributes["weather_code_meaning"], self.wxmeaning)
def set_up_wxcube( data=np.ones((16, 16), dtype=np.int8), time=datetime.datetime(2018, 9, 12, 5, 43), time_bounds=None, frt=datetime.datetime(2018, 9, 12, 3), lat_lon=False, ): """ Set up a wxcube for a particular time and location, which can cover the terminator and test the "update_daynight" functionality Args: data (numpy array): The weather codes with which to populate the array. time (datetime.datetime): Validity time for cube. time_bounds ([datetime.datetime, datetime.datetime]): Validity time bounds. frt (datetime.datetime): Forecast reference time for cube. lat_lon (bool): If True, returns a cube on a lat-lon grid. If False, returns equal area. Returns: iris.cube.Cube: cube of weather codes set to 1 data shape (time_points, 16, 16) """ kwargs = { "name": "weather_code", "units": 1, "time": time, "time_bounds": time_bounds, "frt": frt, "attributes": weather_code_attributes(), "spatial_grid": "equalarea", "domain_corner": (0, -30000), } if lat_lon: kwargs.update({ "spatial_grid": "latlon", "domain_corner": (49, -8), "grid_spacing": 1 }) cube = set_up_variable_cube(data, **kwargs) return cube
def wxcode_fixture(): """Weather symbols cube (randomly sampled data in expected range)""" data = np.random.randint(0, high=31, size=(3, 3)) attributes = { "source": "IMPROVER", "institution": "Met Office", "title": "IMPROVER Post-Processed Multi-Model Blend on 2 km Standard Grid", "mosg__model_configuration": "uk_det uk_ens", } attributes.update(weather_code_attributes()) cube = set_up_variable_cube( data, name="weather_code", units="1", attributes=attributes, spatial_grid="equalarea", ) _update_blended_time_coords(cube) return cube
def set_up_wxcube(time_points=None, lat_lon=False): """ Set up a wxcube for a particular time and location, which can cover the terminator and test the "update_daynight" functionality Args: time_points (list of datetime.datetime): List of time points as datetime instances lat_lon (bool): If True, returns a cube on a lat-lon grid. If False, returns equal area. Returns: iris.cube.Cube: cube of weather codes set to 1 data shape (time_points, 16, 16) """ kwargs = { "name": "weather_code", "units": 1, "time": datetime.datetime(2018, 9, 12, 5, 43), "frt": datetime.datetime(2018, 9, 12, 3), "attributes": weather_code_attributes(), "spatial_grid": "equalarea", "domain_corner": (0, -30000), } if lat_lon: kwargs.update({ "spatial_grid": "latlon", "domain_corner": (49, -8), "grid_spacing": 1 }) cube = set_up_variable_cube(np.ones((16, 16), dtype=np.float32), **kwargs) if time_points is not None: cube = add_coordinate(cube, time_points, "time", is_datetime=True) return cube
def test_values(self): """Test attribute values are correctly set.""" result = weather_code_attributes() self.assertArrayEqual(result["weather_code"], self.wxcode) self.assertEqual(result["weather_code_meaning"], self.wxmeaning)