def process(cube: cli.inputcube): """Sets night values to zero for UV index. Args: cube (iris.cube.Cube): Cube that will have night values set to zero. This should contain either diagnostic values or probabilities of UV index above threshold. Returns: iris.cube.Cube: Input cube with all night values set to zero. Raises: ValueError: If input cube is suspicious, within reason. Note that this is a general check: the CLI expects a cube of UV index or probability of UV index above thresold, and will raise an error if given a probability below threshold, but will not recognise a completely inappropriate cube (eg temperature in Kelvin). Therefore this CLI should be used with care. """ import numpy as np from improver.metadata.probabilistic import is_probability from improver.utilities.solar import DayNightMask if is_probability(cube): if "above_threshold" not in cube.name(): raise ValueError(f"{cube.name()} unsuitable for night masking") mask = DayNightMask()(cube).data # Broadcast mask to shape of input cube to account for additional dimensions. mask = np.broadcast_to(mask, cube.shape) # setting night values to zero. cube.data = np.where(mask == DayNightMask().night, 0, cube.data) return cube
def daynight_interpolate(interpolated_cube): """ Set linearly interpolated data to zero for parameters (e.g. solar radiation parameters) which are zero if the sun is below the horizon. Args: interpolated_cube (iris.cube.Cube): cube containing Linear interpolation of cube at interpolation times in time_list. Returns: interpolated_cubes (iris.cube.CubeList): A list of cubes interpolated to the desired times. """ interpolated_cubes = iris.cube.CubeList() daynightplugin = DayNightMask() daynight_mask = daynightplugin.process(interpolated_cube) for i, single_time in enumerate(interpolated_cube.slices_over('time')): index = np.where(daynight_mask.data[i] == daynightplugin.night) if len(single_time.shape) > 2: single_time.data[..., index[0], index[1]] = 0.0 else: single_time.data[index] = 0.0 interpolated_cubes.append(single_time) return interpolated_cubes
def test_basic_daynight_mask(self): """ Test this create a blank mask cube""" result = DayNightMask()._create_daynight_mask(self.cube) self.assertIsInstance(result, iris.cube.Cube) self.assertEqual(result.long_name, 'day_night_mask') self.assertEqual(result.units, unit.Unit('1')) self.assertEqual(result.data.min(), DayNightMask().night) self.assertEqual(result.data.max(), DayNightMask().night)
def test_basic_daynight_mask(self): """ Test this create a blank mask cube""" result = DayNightMask()._create_daynight_mask(self.cube) self.assertIsInstance(result, iris.cube.Cube) self.assertEqual(result.long_name, "day_night_mask") self.assertEqual(result.units, unit.Unit("1")) self.assertEqual(result.data.min(), DayNightMask().night) self.assertEqual(result.data.max(), DayNightMask().night) self.assertEqual(result.attributes["title"], "Day-Night mask") self.assertEqual(result.attributes["institution"], "Met Office") self.assertEqual(result.dtype, np.int32)
def setUp(self): """Set up the cube for testing.""" cube = set_up_cube_lat_long() lon_points = np.linspace(-8, 7, 16) lon_points_360 = np.linspace(345, 360, 16) lat_points = np.linspace(49, 64, 16) cube.coord('latitude').points = lat_points cube.coord('longitude').points = lon_points self.mask_cube = DayNightMask()._create_daynight_mask(cube)[0] cube_360 = cube.copy() cube_360.coord('longitude').points = lon_points_360 self.mask_cube_360 = DayNightMask()._create_daynight_mask(cube_360)[0]
def test_basic_lat_lon_360(self): """Test day_night mask with lat lon data 360 data.""" result = DayNightMask().process(self.cube_lat_lon_360) expected_result = np.array( [ [ [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ] ] ) self.assertArrayEqual(result.data, expected_result)
def test_basic_standard_grid_ccrs(self): """Test day_night mask with standard_grid_ccrs projection.""" result = DayNightMask().process(self.cube) expected_result = np.array( [ [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ] ] ) self.assertArrayEqual(result.data, expected_result)
def test_time_as_dimension(self): """Test day_night mask for a cube with multiple times.""" cube1 = self.cube.copy() cube1.coord("time").points = np.array(self.dtval + 7.5 + 30.0) cubes = iris.cube.CubeList( [iris.util.squeeze(self.cube), iris.util.squeeze(cube1)]) cube = cubes.merge_cube() result = DayNightMask().process(cube) expected_result = np.array([ [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ], np.ones((16, 16)), ]) self.assertArrayEqual(result.data, expected_result) self.assertEqual(result.shape, cube.shape)
def test_time_as_dimension(self): """Test day_night mask for a cube with multiple times.""" datetime_points = [ datetime(2015, 11, 20, 8, 0), datetime(2015, 11, 20, 14, 0) ] cube = add_coordinate(self.cube, datetime_points, "time", is_datetime=True) result = DayNightMask().process(cube) expected_result = np.array([ [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ], np.ones((16, 16)), ]) self.assertArrayEqual(result.data, expected_result) self.assertEqual(result.shape, cube.shape)
def test_basic_lat_lon_cube(self): """ Test this create a blank mask cube""" day_of_year = 10 utc_hour = 12.0 expected_result = np.ones((16, 16)) result = DayNightMask()._daynight_lat_lon_cube(self.mask_cube, day_of_year, utc_hour) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayEqual(result.data, expected_result)
def test_basic_lat_lon_cube_360(self): """ Test this still works with 360 data""" day_of_year = 10 utc_hour = 0.0 expected_result = np.zeros((16, 16)) result = DayNightMask()._daynight_lat_lon_cube(self.mask_cube_360, day_of_year, utc_hour) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayEqual(result.data, expected_result)
def setUp(self): """Set up the cube for testing.""" data = np.ones((16, 16), dtype=np.float32) cube = set_up_variable_cube( data, "precipitation_amount", "kg m^-2", grid_spacing=1, domain_corner=(49, -8), ) self.mask_cube = DayNightMask()._create_daynight_mask(cube) cube = set_up_variable_cube( data, "precipitation_amount", "kg m^-2", grid_spacing=1, domain_corner=(49, 345), ) self.mask_cube_360 = DayNightMask()._create_daynight_mask(cube)
def process(cube: cli.inputcube): """Sets night values to zero for UV index. Args: cube (iris.cube.Cube): Cube that will have night values set to zero. Returns: iris.cube.Cube: Input cube with all night values set to zero. """ import numpy as np from improver.utilities.solar import DayNightMask mask = DayNightMask()(cube).data # Broadcast mask to shape of input cube to account for additional dimensions. mask = np.broadcast_to(mask, cube.shape) # setting night values to zero. cube.data = np.where(mask == DayNightMask().night, 0, cube.data) return cube
def daynight_interpolate(interpolated_cube: Cube) -> CubeList: """ Set linearly interpolated data to zero for parameters (e.g. solar radiation parameters) which are zero if the sun is below the horizon. Args: interpolated_cube: cube containing Linear interpolation of cube at interpolation times in time_list. Returns: A list of cubes interpolated to the desired times. """ daynightplugin = DayNightMask() daynight_mask = daynightplugin(interpolated_cube) index = daynight_mask.data == daynightplugin.night interpolated_cube.data[..., index] = 0.0 return iris.cube.CubeList(list(interpolated_cube.slices_over("time")))
def test_basic_repr(self): """ Test Representation string of DayNightMask Object""" expected = '<DayNightMask : Day = 1, Night = 0>' result = str(DayNightMask()) self.assertEqual(result, expected)
def test_basic_init(self): """ Test Initiation of DayNightMask Object""" plugin = DayNightMask() self.assertEqual(plugin.day, 1) self.assertEqual(plugin.night, 0)