def test_basic_global(self): """Test process returns a wxcode cube with right values for global. """ plugin = WeatherSymbols(wxtree="global") cubes = self.cubes.extract(self.gbl) result = plugin.process(cubes) self.assertArrayAndMaskEqual(result.data, self.expected_wxcode_no_lightning)
def test_no_lightning(self): """Test process returns right values if no lightning. """ plugin = WeatherSymbols() cubes = self.cubes.extract(self.uk_no_lightning) result = plugin.process(cubes) self.assertArrayAndMaskEqual(result.data, self.expected_wxcode_no_lightning)
def test_weather_data_global(self): """Test process returns the right weather values global part2 """ plugin = WeatherSymbols(wxtree='global') data_snow = np.array([ 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.1, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0 ]).reshape(3, 1, 3, 3) data_rain = np.array([ 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]).reshape(3, 1, 3, 3) data_cloud = np.array([ 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0 ]).reshape(2, 1, 3, 3) data_cld_low = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).reshape(1, 1, 3, 3) data_vis = np.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]).reshape(2, 1, 3, 3) cubes = set_up_wxcubes_global() cubes[0].data = data_snow cubes[1].data = data_rain cubes[2].data = data_cloud cubes[3].data = data_cld_low cubes[4].data = data_vis result = plugin.process(cubes) expected_wxcode = np.array([14, 15, 17, 18, 23, 24, 26, 27, 27]).reshape(1, 3, 3) self.assertArrayEqual(result.data, expected_wxcode)
def test_weather_data_global(self): """Test process returns the right weather values global part2 """ plugin = WeatherSymbols(wxtree='global') data_snow = np.array([ 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.1, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0 ]).reshape((3, 3, 3)) data_rain = np.array([ 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]).reshape((3, 3, 3)) data_cloud = np.array([ 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0 ]).reshape((2, 3, 3)) data_cld_low = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).reshape((1, 3, 3)) data_vis = np.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]).reshape((2, 3, 3)) cubes = self.cubes.extract(self.gbl) cubes[0].data = data_snow cubes[1].data = data_rain cubes[2].data = data_cloud cubes[3].data = data_cld_low cubes[4].data = data_vis result = plugin.process(cubes) self.assertArrayEqual(result.data, self.expected_wxcode_alternate)
def test_raises_error_missing_cubes_global(self): """Test check_input_cubes method raises error if data is missing""" plugin = WeatherSymbols(wxtree='global') cubes = set_up_wxcubes_global()[0:3] msg = 'Weather Symbols input cubes are missing' with self.assertRaisesRegex(IOError, msg): plugin.check_input_cubes(cubes)
def test_no_lightning(self): """Test check_input_cubes raises no error if lightning missing""" plugin = WeatherSymbols() result = plugin.check_input_cubes(self.cubes_no_lightning) self.assertIsInstance(result, dict) self.assertEqual(len(result), 1) self.assertTrue('lightning' in result)
def test_day_night(self): """Test process returns the right values for night. """ plugin = WeatherSymbols() for i, cube in enumerate(self.cubes): self.cubes[i].coord("time").points = cube.coord("time").points + 3600 * 12 result = plugin.process(self.cubes) self.assertArrayEqual(result.data, self.expected_wxcode_night)
def test_sleet(self): """Test process returns the sleet weather code.""" plugin = WeatherSymbols() data_snow = np.zeros_like(self.cubes[0].data) data_sleet = np.ones_like(self.cubes[0].data) data_rain = np.zeros_like(self.cubes[0].data) # pylint: disable=no-member data_precip = np.maximum.reduce([data_snow, data_sleet, data_rain]) data_precipv = np.ones_like(self.cubes[0].data) data_cloud = np.ones_like(self.cubes[4].data) data_cld_low = np.ones_like(self.cubes[5].data) data_vis = np.zeros_like(self.cubes[6].data) data_lightning = np.zeros_like(self.cubes[7].data) expected = np.ones_like(self.expected_wxcode_alternate) * 18 cubes = self.cubes cubes[0].data = data_snow cubes[1].data = data_sleet cubes[2].data = data_rain cubes[3].data = data_precipv cubes[4].data = data_cloud cubes[5].data = data_cld_low cubes[6].data = data_vis cubes[7].data = data_lightning cubes[8].data = data_precip result = plugin.process(cubes) self.assertArrayEqual(result.data, expected)
def test_basic(self): """Test find_all_routes returns a list of expected nodes.""" plugin = WeatherSymbols() result = plugin.find_all_routes(self.test_graph, 'start_node', 3) expected_nodes = [['start_node', 'fail_0', 3]] self.assertIsInstance(result, list) self.assertListEqual(result, expected_nodes)
def test_works_with_lists(self): """Test that the construct_condition method works with a list of Constraints. """ plugin = WeatherSymbols() constraint_list = [ iris.Constraint( name='probability_of_lwe_snowfall_rate_above_threshold', coord_values={'threshold': 0.03}), iris.Constraint( name='probability_of_rainfall_rate_above_threshold', coord_values={'threshold': 0.03}) ] condition = '<' prob_threshold = 0.5 gamma = 0.7 expected = ("(cubes.extract(Constraint(name=" "'probability_of_lwe_snowfall_rate_above_threshold', " "coord_values={'threshold': 0.03}))[0].data - " "cubes.extract(Constraint(name=" "'probability_of_rainfall_rate_above_threshold', " "coord_values={'threshold': 0.03}))[0].data * 0.7) < 0.5") result = plugin.construct_condition(constraint_list, condition, prob_threshold, gamma) self.assertIsInstance(result, str) self.assertEqual(result, expected)
def test_list_of_constraints(self): """Test construct_extract_constraint returns a list of iris.Constraint.""" plugin = WeatherSymbols() diagnostics = [ 'probability_of_rainfall_rate_above_threshold', 'probability_of_lwe_snowfall_rate_above_threshold' ] thresholds = [ AuxCoord(0.03, units='mm hr-1'), AuxCoord(0.03, units='mm hr-1') ] result = plugin.construct_extract_constraint(diagnostics, thresholds, False) expected = ("iris.Constraint(" "name='probability_of_lwe_snowfall_rate_above_threshold', " "lwe_snowfall_rate=lambda cell: 0.03 * {t_min} < cell " "< 0.03 * {t_max})".format( t_min=(1. - WeatherSymbols().float_tolerance), t_max=(1. + WeatherSymbols().float_tolerance))) self.assertIsInstance(result, list) self.assertIsInstance(result[1], str) self.assertEqual(len(result), 2) self.assertEqual(result[1], expected)
def test_raises_error_missing_cubes_global(self): """Test check_input_cubes method raises error if data is missing""" plugin = WeatherSymbols(wxtree="global") cubes = self.cubes.extract(self.gbl)[0:3] msg = "Weather Symbols input cubes are missing" with self.assertRaisesRegex(IOError, msg): plugin.check_input_cubes(cubes)
def test_raises_error_missing_cubes(self): """Test check_input_cubes method raises error if data is missing""" plugin = WeatherSymbols() cubes = self.cubes.pop() msg = 'Weather Symbols input cubes are missing' with self.assertRaisesRegex(IOError, msg): plugin.check_input_cubes(cubes)
def test_basic(self): """Test that the format_condition_chain method returns a string.""" plugin = WeatherSymbols() conditions = ['condition1', 'condition2'] expected = '(condition1) & (condition2)' result = plugin.format_condition_chain(conditions) self.assertIsInstance(result, str) self.assertEqual(result, expected)
def test_works_with_or(self): """Test that the format_condition_chain method works with OR.""" plugin = WeatherSymbols() conditions = ["condition1", "condition2"] expected = "(condition1) | (condition2)" result = plugin.format_condition_chain(conditions, condition_combination="OR") self.assertIsInstance(result, str) self.assertEqual(result, expected)
def test_multiple_routes(self): """Test finds multiple routes.""" plugin = WeatherSymbols() result = plugin.find_all_routes(self.test_graph, 'start_node', 1) expected_nodes = [['start_node', 'success_1', 'success_1_1', 1], ['start_node', 'fail_0', 'success_0_1', 1]] self.assertIsInstance(result, list) self.assertListEqual(result, expected_nodes)
def test_raises_error_missing_threshold(self): """Test check_input_cubes method raises error if data is missing""" plugin = WeatherSymbols() cubes = self.cubes cubes[0] = cubes[0][0] msg = "Weather Symbols input cubes are missing" with self.assertRaisesRegex(IOError, msg): plugin.check_input_cubes(cubes)
def test_incorrect_units(self): """Test that check_input_cubes method raises an error if the units are incompatible between the input cube and the decision tree.""" plugin = WeatherSymbols() msg = "Unable to convert from" self.cubes[0].coord('threshold').units = Unit('mm kg-1') with self.assertRaisesRegexp(ValueError, msg): plugin.check_input_cubes(self.cubes)
def test_basic(self): """Test that the invert_condition method returns a tuple of strings.""" plugin = WeatherSymbols() tree = plugin.queries result = plugin.invert_condition(tree[list(tree.keys())[0]]) self.assertIsInstance(result, tuple) self.assertEqual(len(result), 2) self.assertIsInstance(result[0], str) self.assertIsInstance(result[1], str)
def test_day_night(self): """Test process returns the right values for night. """ plugin = WeatherSymbols() for i, cube in enumerate(self.cubes): self.cubes[i].coord('time').points = (cube.coord('time').points + 11.5) result = plugin.process(self.cubes) expected_wxcode = np.array([0, 2, 5, 6, 7, 8, 9, 11, 12]).reshape(1, 3, 3) self.assertArrayEqual(result.data, expected_wxcode)
def test_basic(self): """Test construct_extract_constraint method returns a iris.Constraint. or list of iris.Constraint""" plugin = WeatherSymbols() result = plugin.create_symbol_cube(self.cube[0]) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayEqual(result.attributes['weather_code'], self.wxcode) self.assertEqual(result.attributes['weather_code_meaning'], self.wxmeaning)
def test_invert_combination_correctly(self): """Test invert_condition inverts combination correctly.""" plugin = WeatherSymbols() node = {"threshold_condition": ">=", "condition_combination": ""} possible_inputs = ["AND", "OR", ""] inverse_outputs = ["OR", "AND", ""] for i, val in enumerate(possible_inputs): node["condition_combination"] = val result = plugin.invert_condition(node) self.assertEqual(result[1], inverse_outputs[i])
def test_omit_nodes_top_node(self): """Test find_all_routes where omit node is top node.""" omit_nodes = {"start_node": "success_1"} plugin = WeatherSymbols() result = plugin.find_all_routes( self.test_graph, "start_node", 1, omit_nodes=omit_nodes, ) expected_nodes = [["success_1", "success_1_1", 1]] self.assertIsInstance(result, list) self.assertListEqual(result, expected_nodes)
def test_omit_nodes_blocked(self): """Test find_all_routes where omitted node is no longer accessible.""" omit_nodes = {"fail_0": 3} plugin = WeatherSymbols() result = plugin.find_all_routes( self.test_graph, "start_node", 5, omit_nodes=omit_nodes, ) expected_nodes = [] self.assertIsInstance(result, list) self.assertListEqual(result, expected_nodes)
def test_omit_nodes_multi(self): """Test find_all_routes where multiple omitted nodes.""" omit_nodes = {"fail_0": 3, "success_1": "success_1_1"} plugin = WeatherSymbols() result = plugin.find_all_routes( self.test_graph, "start_node", 1, omit_nodes=omit_nodes, ) expected_nodes = [["start_node", "success_1_1", 1]] self.assertIsInstance(result, list) self.assertListEqual(result, expected_nodes)
def test_basic(self): """Test process returns a weather code cube with right values and type. """ plugin = WeatherSymbols() result = plugin.process(self.cubes) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayEqual(result.attributes["weather_code"], self.wxcode) self.assertEqual(result.attributes["weather_code_meaning"], self.wxmeaning) self.assertArrayEqual(result.data, self.expected_wxcode) self.assertEqual(result.dtype, np.int32)
def test_invert_combination_correctly(self): """Test invert_condition inverts combination correctly.""" plugin = WeatherSymbols() node = {'threshold_condition': '>=', 'condition_combination': ''} possible_inputs = ['AND', 'OR', ''] inverse_outputs = ['OR', 'AND', ''] for i, val in enumerate(possible_inputs): node['condition_combination'] = val result = plugin.invert_condition(node) self.assertEqual(result[1], inverse_outputs[i])
def test_error(self): """Test that the _invert_comparator method raises an error when the condition cannot be inverted.""" plugin = WeatherSymbols() possible_inputs = ["==", "!=", "NOT", "XOR"] for val in possible_inputs: with self.assertRaisesRegex( KeyError, f"Unexpected condition {val}, cannot invert it."): plugin._invert_comparator(val)
def test_weather_data_global(self): """Test process returns the right weather values global part2 """ plugin = WeatherSymbols(wxtree="global") data_snow = np.array( [ [[0.0, 0.0, 0.0], [0.0, 1.0, 1.0], [1.0, 1.0, 0.1]], [[0.0, 0.0, 0.0], [0.0, 1.0, 1.0], [1.0, 1.0, 0.0]], [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [1.0, 1.0, 1.0]], ], dtype=np.float32, ) data_sleet = np.array( [ [[0.0, 0.0, 1.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]], [[0.0, 0.0, 1.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]], [[0.0, 0.0, 1.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]], ], dtype=np.float32, ) data_rain = np.array( [ [[1.0, 1.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], [[1.0, 1.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], [[1.0, 1.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], ], dtype=np.float32, ) data_cloud = np.array( [ [[0.0, 1.0, 0.0], [1.0, 0.0, 1.0], [0.0, 1.0, 1.0]], [[0.0, 1.0, 0.0], [1.0, 0.0, 1.0], [0.0, 1.0, 1.0]], ], dtype=np.float32, ) data_cld_low = np.zeros((3, 3), dtype=np.float32) data_vis = np.zeros((2, 3, 3), dtype=np.float32) data_precip = np.max(np.array([data_snow, data_sleet, data_rain]), axis=0) data_convective_ratio = np.array( [[1.0, 0.0, 1.0], [0.0, 1.0, 0.0], [1.0, 0.0, 0.0]], dtype=np.float32, ) cubes = self.cubes.extract(self.gbl) cubes[0].data = data_snow cubes[1].data = data_sleet cubes[2].data = data_rain cubes[3].data = data_cloud cubes[4].data = data_cld_low cubes[5].data = data_vis cubes[6].data = data_precip cubes[7].data = data_convective_ratio result = plugin.process(cubes) self.assertArrayAndMaskEqual(result.data, self.expected_wxcode_alternate)
def test_no_lightning(self): """Test process returns right values if no lightning. """ plugin = WeatherSymbols() result = plugin.process(self.cubes_no_lightning) self.assertIsInstance(result, iris.cube.Cube) self.assertArrayEqual(result.attributes['weather_code'], self.wxcode) self.assertEqual(result.attributes['weather_code_meaning'], self.wxmeaning) expected_wxcode = np.array([1, 3, 5, 6, 7, 8, 10, 11, 12]).reshape(1, 3, 3) self.assertArrayEqual(result.data, expected_wxcode)