def setUp(self): """Set up template with data, coordinates, attributes and cell methods""" self.template_cube = set_up_variable_cube( 280 * np.ones((3, 5, 5), dtype=np.float32), standard_grid_metadata="uk_det") self.template_cube.add_cell_method("time (max): 1 hour") self.name = "lwe_precipitation_rate" self.units = "mm h-1" self.mandatory_attributes = MANDATORY_ATTRIBUTE_DEFAULTS.copy()
def europe_grid_fixture() -> Cube: data = np.zeros((10, 10), dtype=np.float32) cube = set_up_variable_cube( data, name="template", grid_spacing=1, domain_corner=(45, -5), attributes=GLOBAL_ATTRIBUTES, ) return cube
def test_frt_hour_mismatch(self): """Test an error is raised when the forecast_reference_time mismatches""" self.adjusted_cube = set_up_variable_cube( self.data, frt=datetime.datetime(2017, 11, 10, 2, 0), time=datetime.datetime(2017, 11, 10, 5, 0), ) with self.assertRaisesRegex(ValueError, self.message): forecast_coords_match(self.ref_cube, self.adjusted_cube)
def test_ordering_for_realization_coordinate(self): """Test that the cube has been reordered, if it is originally in an undesirable order and the cube contains a "realization" coordinate.""" cube = set_up_variable_cube(np.ones((3, 3, 3), dtype=np.float32)) cube.transpose([2, 1, 0]) save_netcdf(cube, self.filepath) result = load_cube(self.filepath) self.assertEqual(result.coord_dims("realization")[0], 0) self.assertArrayAlmostEqual(result.coord_dims("latitude")[0], 1) self.assertArrayAlmostEqual(result.coord_dims("longitude")[0], 2)
def setUp(self): """Create test cubes""" # Create 2D test cube data = np.ones((5, 5), dtype=np.float32) data[2, 2] = 0 self.cube = set_up_variable_cube( data, spatial_grid="equalarea", ) # Create 3D test cube with 2 realizations data = np.ones((2, 5, 5), dtype=np.float32) self.multi_realization_cube = set_up_variable_cube( data, spatial_grid="equalarea", )
def test_incorrect_inputs_exception(): """Tests that the expected exception is raised for incorrectly named input cubes.""" temperature = set_up_variable_cube(np.ones((2, 2)).astype(FLOAT_DTYPE)) expected = ( "A cloud area fraction and convective ratio are required, " f"but the inputs were: {temperature.name()}, {temperature.name()}") with pytest.raises(ValueError, match=expected): ShowerConditionProbability()(CubeList([temperature, temperature]))
def setUp(self): """Use temperature cube to test with.""" data = 275 * np.ones((3, 3, 3), dtype=np.float32) self.cube = set_up_variable_cube(data) self.extra_dim_coord = DimCoord(np.array([5.0], dtype=np.float32), standard_name="height", units="m") self.extra_aux_coord = AuxCoord(["uk_det", "uk_ens", "gl_ens"], long_name="model", units="no_unit")
def test_45_minute_frt_offset_match(self): """Test returns None when cubes time coordinates match with an allowed leniency for a 45 minute offset.""" adjusted_cube = set_up_variable_cube( self.data, frt=datetime.datetime(2017, 11, 10, 1, 45), time=datetime.datetime(2017, 11, 10, 4, 0), ) self.assertIsNone(forecast_coords_match(self.ref_cube, adjusted_cube))
def test_forecast_period_mismatch(self): """Test an error is raised when the forecast period mismatches.""" adjusted_cube = set_up_variable_cube( self.data, frt=datetime.datetime(2017, 11, 10, 1, 0), time=datetime.datetime(2017, 11, 10, 5, 0), ) with self.assertRaisesRegex(ValueError, self.message): forecast_coords_match(self.ref_cube, adjusted_cube)
def setup_orographic_enhancement_cube(): """Set up an orogrpahic enhancement cube using central utilities""" data = np.array([[1, 1, 1], [0, 1, 0], [0, 0, 0], [0, 0, 0]], dtype=np.float32) orographic_enhancement_cube = set_up_variable_cube( data, name="orographic_enhancement", units="mm/hr", spatial_grid="equalarea") return orographic_enhancement_cube
def test_failure_outside_domain(self): """Test failure if the cutout begins outside the grid domain""" grid = set_up_variable_cube(np.ones((10, 10), dtype=np.float32), spatial_grid="equalarea") cutout = grid.copy() grid_spacing = calculate_grid_spacing(cutout, cutout.coord(axis="x").units) cutout.coord(axis="x").points = (cutout.coord(axis="x").points - 10 * grid_spacing) self.assertFalse(grid_contains_cutout(grid, cutout))
def setUp(self): """ Create a raw and calibrated cube with with forecast_reference_time and forecast_period coordinates. """ self.raw_cube = set_up_variable_cube(ECC_TEMPERATURE_REALIZATIONS) self.post_processed_percentiles = set_up_percentile_cube( np.sort(ECC_TEMPERATURE_REALIZATIONS, axis=0), np.array([10, 50, 90], dtype=np.float32), )
def test_basic(): """Test that a collapsed cube is returned with no realization coord""" data = np.full((3, 3, 3), fill_value=281.0, dtype=np.float32) cube = set_up_variable_cube(data, realizations=[0, 1, 2]) result = collapse_realizations(cube) assert "realization" not in [ coord.name() for coord in result.dim_coords + result.aux_coords ] assert (result.data == np.full((3, 3), fill_value=281.0, dtype=np.float32)).all()
def setUp(self): """Set up the cube for testing.""" data = np.ones((1, 16, 16), dtype=np.float32) data[:, 7, 7] = 0.0 attributes = {"institution": "Met Office", "title": "A model field"} self.cube = set_up_variable_cube(data, "precipitation_amount", "kg m^-2", "equalarea", attributes=attributes)
def setup_for_mock(): """Function that returns a CubeList of wind_speed and wind_from_direction These cubes should be the same as the setup cubes. Returns: iris.cube.CubeList: The CubeList. """ return CubeList( [ set_up_variable_cube( data=np.zeros((2, 2), dtype=np.float32), name="wind_speed" ), set_up_variable_cube( data=np.zeros((2, 2), dtype=np.float32), name="wind_from_direction" ), ] )
def setUp(self): """Set up test velocity and rainfall cubes""" # Skip if pysteps not available pytest.importorskip("pysteps") analysis_time = datetime.datetime(2019, 9, 10, 15) wind_data = 4 * np.ones((8, 8), dtype=np.float32) self.ucube = set_up_variable_cube( wind_data, name="precipitation_advection_x_velocity", units="m/s", spatial_grid="equalarea", time=analysis_time, frt=analysis_time, ) self.vcube = set_up_variable_cube( wind_data, name="precipitation_advection_y_velocity", units="m/s", spatial_grid="equalarea", time=analysis_time, frt=analysis_time, ) self.rain_cube = _make_initial_rain_cube(analysis_time) self.interval = 15 self.max_lead_time = 120 self.orogenh_cube = _make_orogenh_cube(analysis_time, self.interval, self.max_lead_time) self.plugin = PystepsExtrapolate(self.interval, self.max_lead_time) # set up all grids with 3.6 km spacing (1 m/s = 3.6 km/h, # using a 15 minute time step this is one grid square per step) xmin = 0 ymin = 200000 step = 3600 xpoints = np.arange(xmin, xmin + 8 * step, step).astype(np.float32) ypoints = np.arange(ymin, ymin + 8 * step, step).astype(np.float32) for cube in [ self.ucube, self.vcube, self.rain_cube, self.orogenh_cube ]: cube.coord(axis="x").points = xpoints cube.coord(axis="y").points = ypoints
def setUp(self): """Set up a cube.""" data = np.ones((1, 16, 16), dtype=np.float32) self.cube = set_up_variable_cube( data, "precipitation_amount", "kg m^-2", "equalarea", ) self.squeezed_cube = iris.util.squeeze(self.cube)
def test_error_unmatched_realizations(self): """Test error is raised if the realizations provided do not match the data dimensions""" realizations_len = 4 data_len = len(self.data_3d[0]) msg = "Cannot generate {} realizations with data of length {}".format( realizations_len, data_len) with self.assertRaisesRegex(ValueError, msg): _ = set_up_variable_cube(self.data_3d, realizations=np.arange(realizations_len))
def test_failure_partial_overlap(self): """Test failure if the cutout is only partially included in the grid""" grid = set_up_variable_cube( np.ones((10, 10), dtype=np.float32), spatial_grid="equalarea" ) cutout = grid.copy() grid_spacing = calculate_grid_spacing(cutout, cutout.coord(axis="x").units) cutout.coord(axis="x").points = cutout.coord(axis="x").points + 2 * grid_spacing self.assertFalse(grid_contains_cutout(grid, cutout))
def test_error_unmatched_height_levels(self): """Test error is raised if the heights provided do not match the data dimensions""" height_levels_len = 4 data_len = len(self.data_3d[0]) msg = "Cannot generate {} heights with data of length {}".format( height_levels_len, data_len) with self.assertRaisesRegex(ValueError, msg): _ = set_up_variable_cube( self.data_3d, height_levels=np.arange(height_levels_len))
def landmask_fixture(): """Static ancillary cube (no attributes or time coordinates)""" data = np.arange(9).reshape(3, 3).astype(np.float32) cube = set_up_variable_cube(data, name="land_binary_mask", units="1", spatial_grid="equalarea") for coord in ["time", "forecast_reference_time", "forecast_period"]: cube.remove_coord(coord) return cube
def test_error_not_enough_dimensions(self): """Test error is raised if 3D input cube and both realizations and heights provided""" realizations = [0, 3, 4] height_levels = [1.5, 3.0, 4.5] msg = ("Input data must have 4 dimensions to add both realization " "and height coordinates: got 3") with self.assertRaisesRegex(ValueError, msg): _ = set_up_variable_cube(self.data_3d, realizations=realizations, height_levels=height_levels)
def gradient_fixture() -> Cube: """Gradient cube with several gradient values.""" data = np.array([0, 0.5, -1.0, 5.0], dtype=np.float32) data = np.stack([data] * 2) cube = set_up_variable_cube(data, name="gradient_of_surface_altitude", units="1", spatial_grid="equalarea") return cube
def setUp(self): """Set up additional cube for land-sea mask.""" super().setUp() mask_data = np.array([[0, 1, 0], [0, 1, 1], [1, 1, 0]], dtype=np.int32) self.mask_cube = set_up_variable_cube(mask_data, name="land_binary_mask", units="1") self.plugin = Plugin("norm", "20171110T0000Z") # Copy a few slices of the temperature truth cube to test on. self.cube3D = self.temperature_truth_cube[0:2, ...].copy()
def wind_speed_fixture() -> Cube: """Wind speed in m/s""" data = np.array([[0, 1, 2], [2, 3, 4], [4, 5, 6]], dtype=np.float32) cube = set_up_variable_cube(data, name="wind_speed", units="m s^-1", spatial_grid="equalarea") for axis in ["x", "y"]: cube.coord(axis=axis).points = np.array([0, 1, 2], dtype=np.float32) return cube
def test_create_regrid_cube(): """Test the create_regrid_cube function""" source_cube_latlon = set_up_variable_cube( np.ones((2, 5, 5), dtype=np.float32), time=datetime(2018, 11, 10, 8, 0), frt=datetime(2018, 11, 10, 0, 0), ) target_cube_equalarea = set_up_variable_cube( np.ones((10, 10), dtype=np.float32), spatial_grid="equalarea" ) data = np.repeat(1.0, 200).reshape(2, 10, 10) cube_v = create_regrid_cube(data, source_cube_latlon, target_cube_equalarea) assert cube_v.shape == (2, 10, 10) assert cube_v.coord(axis="x").standard_name == "projection_x_coordinate" assert cube_v.coord(axis="y").standard_name == "projection_y_coordinate" assert cube_v.coord("forecast_reference_time") == source_cube_latlon.coord( "forecast_reference_time" )
def setUp(self): """Set up cube.""" data = np.array([[1, 2, 3], [2, 4, 6], [5, 10, 15]]) self.cube = set_up_variable_cube( data, "wind_speed", "m s-1", "equalarea", ) self.plugin = DifferenceBetweenAdjacentGridSquares()
def setUp(self): """Set up orography cube (as zeros) and falling_phase_level cube with multiple realizations designed to return snow, sleet and rain. The middle realization gives both not-snow and not-rain because both the 20th percentile is <= zero and the 80th percentile is >= zero.""" # cubes for testing have a grid-length of 2000m. self.plugin = PrecipPhaseProbability(radius=2100.0) self.mandatory_attributes = { "title": "mandatory title", "source": "mandatory_source", "institution": "mandatory_institution", } data = np.zeros((3, 3), dtype=np.float32) orog_cube = set_up_variable_cube( data, name="surface_altitude", units="m", spatial_grid="equalarea", attributes=self.mandatory_attributes, ) falling_level_data = np.array( [ [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1]], [[0, -1, 0], [0, 1, 0], [0, -1, 0]], [[1, 1, 1], [1, 1, 1], [1, 1, 1]], ], dtype=np.float32, ) falling_level_cube = set_up_variable_cube( falling_level_data, units="m", spatial_grid="equalarea", name="altitude_of_snow_falling_level", realizations=[0, 1, 2], attributes=self.mandatory_attributes, ) self.cubes = iris.cube.CubeList([falling_level_cube, orog_cube])
def test_history_already_exists(self): """Test that the history attribute is overwritten, if it already exists.""" cube = set_up_variable_cube(np.ones((3, 3), dtype=np.float32)) old_history = "2018-09-13T11:28:29: StaGE" cube.attributes["history"] = old_history set_history_attribute(cube, "Nowcast") self.assertTrue("history" in cube.attributes) self.assertTrue("Nowcast" in cube.attributes["history"]) self.assertFalse(old_history in cube.attributes["history"])
def test_coordinate_input(self): """Test the expected hash is returned when input is a cube coordinate.""" cube = set_up_variable_cube(np.ones((3, 3)).astype(np.float32)) hash_input = cube.coord("latitude") result = generate_hash(hash_input) expected = "ee6a057f5eeef0e94a853cfa98f3c22b121dda31ada3378ce9466e48d06f9887" self.assertIsInstance(result, str) self.assertEqual(result, expected)