def test_dims_mismatch_error(): """Test the process function with mismatched dimensions""" rain, snow = setup_cubes(snow_data=np.array([[0, 0.5]], dtype=np.float32)) with pytest.raises( ValueError, match="Rain and snow cubes are not on the same grid" ): SnowFraction()(iris.cube.CubeList([rain, snow]))
def process(*cubes: cli.inputcube, model_id_attr: str = None): """ Calculates a snow-fraction field from fields of snow and rain (rate or accumulation). Where no precipitation is present, the data are filled in from the nearest precipitating point. snow_fraction = snow / (snow + rain) Args: cubes (iris.cube.CubeList or list): Contains cubes of rain and snow, both must be either rates or accumulations. model_id_attr (str): Name of the attribute used to identify the source model for blending. Returns: iris.cube.Cube: A single cube containing the snow-fraction data. """ from iris.cube import CubeList from improver.precipitation_type.snow_fraction import SnowFraction return SnowFraction(model_id_attr=model_id_attr)(CubeList(cubes))
def test_non_coercing_units_error(): """Test the process function with input cubes of incompatible units""" rain, snow = setup_cubes() rain.units = Unit("K") with pytest.raises( ValueError, match=r"Unable to convert from 'Unit\('m s-1'\)' to 'Unit\('K'\)'." ): SnowFraction()(iris.cube.CubeList([rain, snow]))
def test_coercing_units(): """Test the process function with input cubes of different but compatible units""" rain, snow = setup_cubes() rain.convert_units("mm h-1") result = SnowFraction()(iris.cube.CubeList([rain, snow])) assert str(result.units) == "1" np.testing.assert_allclose(result.data, EXPECTED_DATA) assert rain.units == "mm h-1" assert snow.units == "m s-1"
def test_wrong_input_names_error(): """Test the process function with incorrect input cubes""" rain, snow = setup_cubes() rain.rename("kittens") snow.rename("puppies") with pytest.raises( ValueError, match=r"Could not find both rain and snow in \['kittens', 'puppies'\]", ): SnowFraction()(iris.cube.CubeList([rain, snow]))
def test_masked_data_error(mask_what): """Test the process function with masked data points""" rain, snow = setup_cubes() mask = [[False, False], [False, True]] if "rain" in mask_what: rain.data = np.ma.masked_array(rain.data, mask) if "snow" in mask_what: snow.data = np.ma.masked_array(snow.data, mask) with pytest.raises(ValueError, match=r"Unexpected masked data in input cube\(s\)"): SnowFraction()(iris.cube.CubeList([rain, snow]))
def test_input_name_matches_both_phases_error(): """Test the process function with an input cube that has both rain and snow in its name""" rain, snow = setup_cubes() rain.rename("its_raining_snowy_kittens") snow.rename("puppies") with pytest.raises( ValueError, match="Failed to find unique rain and snow cubes from \['its_raining_snowy_kittens', 'puppies'\]", ): SnowFraction()(iris.cube.CubeList([rain, snow]))
def test_acclen_mismatch_error(): """Test the process function with mismatched accumulation lengths""" rain, snow = setup_cubes(name="thickness_of_{phase}fall_amount") time_coords = construct_scalar_time_coords( [c.point for c in snow.coord("time").cells()], (datetime(2017, 11, 10, 1, 0), datetime(2017, 11, 10, 4, 0)), snow.coord("forecast_reference_time").cell(0).point, ) _ = [snow.replace_coord(coord) for coord, _ in time_coords] with pytest.raises( ValueError, match="Rain and snow cubes do not have the same time coord" ): SnowFraction()(iris.cube.CubeList([rain, snow]))
def test_basic(cube_name, mask_what, model_id_attr): """Run a test with four values, including one with no precip that will trigger divide-by-zero. Check data and metadata of result. Check with and without masked arrays (because divide-by-zero gives a different result, even when input mask is all-False as in this test) and with and without a model_id_attr value. """ rain, snow = setup_cubes(name=cube_name) if "rain" in mask_what: rain.data = np.ma.masked_array(rain.data) if "snow" in mask_what: snow.data = np.ma.masked_array(snow.data) expected_attributes = COMMON_ATTRS.copy() if model_id_attr: expected_attributes[model_id_attr] = rain.attributes[model_id_attr] result = SnowFraction(model_id_attr=model_id_attr)(iris.cube.CubeList([rain, snow])) assert isinstance(result, iris.cube.Cube) assert not isinstance(result.data, np.ma.masked_array) assert str(result.units) == "1" assert result.name() == "snow_fraction" assert result.attributes == expected_attributes np.testing.assert_allclose(result.data, EXPECTED_DATA)
def test_missing_cube_error(): """Test the process function with one cube missing""" rain, _ = setup_cubes() with pytest.raises(ValueError, match="Expected exactly 2 input cubes, found 1"): SnowFraction()(iris.cube.CubeList([rain]))