def test_raise_error_no_time_coordinate(self): """Test that the function raises an error if no time coordinate.""" cube = set_up_wxcube() cube.coord('time').rename('nottime') msg = "cube must have time coordinate" with self.assertRaisesRegex(CoordinateNotFoundError, msg): update_daynight(cube)
def test_wxcode_updated_on_latlon(self): """Test Correct wxcodes returned for lat lon cube.""" cube = set_up_wxcube_lat_lon() cube.data = self.cube_data expected_result = np.array( [[[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3], [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], [6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10], [13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14], [15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15], [16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17], [18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18], [19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20], [22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23], [25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26], [27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27], [28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29]]]) result = update_daynight(cube) self.assertArrayEqual(result.data, expected_result)
def test_wxcode_time_different_seconds(self): """ Test code works if time coordinate has a difference in the number of seconds, which should round to the same time in hours and minutes. This was raised by changes to cftime which altered its precision.""" time_origin = "hours since 1970-01-01 00:00:00" calendar = "gregorian" dateval = datetime.datetime(2018, 9, 12, 5, 42, 59) numdateval = date2num(dateval, time_origin, calendar) time_points = [numdateval] cube = set_up_wxcube(time_points=time_points) cube.data = self.cube_data cube = iris.util.squeeze(cube) expected_result = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3], [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], [6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10], [13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14], [15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15], [16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17], [18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18], [19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20], [22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23], [25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26], [27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27], [28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29]]) result = update_daynight(cube) self.assertArrayEqual(result.data, expected_result) self.assertEqual(result.data.shape, (16, 16))
def test_wxcode_time_as_attribute(self): """ Test code works if time is an attribute not a dimension """ cube = set_up_wxcube() cube.data = self.cube_data cube = iris.util.squeeze(cube) expected_result = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3], [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], [6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10], [13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14], [15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15], [16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17], [18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18], [19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20], [22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23], [25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26], [27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27], [28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29]]) result = update_daynight(cube) self.assertArrayEqual(result.data, expected_result) self.assertEqual(result.data.shape, (16, 16))
def test_basic_lat_lon(self): """Test that the function returns a weather code lat lon cube..""" cube = set_up_wxcube_lat_lon() result = update_daynight(cube) self.assertIsInstance(result, Cube) self.assertEqual(result.name(), 'weather_code') self.assertEqual(result.units, Unit("1")) self.assertArrayEqual(result.attributes['weather_code'], self.wxcode) self.assertEqual(result.attributes['weather_code_meaning'], self.wxmeaning)
def test_wxcode_time_as_array(self): """ Test code works if time is an array of dimension > 1 """ num1 = datetime_to_numdateval(year=2018, month=9, day=12, hour=5, minutes=0) num2 = datetime_to_numdateval(year=2018, month=9, day=12, hour=6, minutes=0) num3 = datetime_to_numdateval(year=2018, month=9, day=12, hour=7, minutes=0) cube = set_up_wxcube(time_points=[num1, num2, num3]) expected_result = np.ones((3, 16, 16)) expected_result[0, :, :] = 0 result = update_daynight(cube) self.assertArrayEqual(result.data, expected_result)
def process(self, cubes): """Apply the decision tree to the input cubes to produce weather symbol output. Args: cubes (iris.cube.CubeList): A cubelist containing the diagnostics required for the weather symbols decision tree, these at co-incident times. Returns: symbols (iris.cube.Cube): A cube of weather symbols. """ # Check input cubes contain required data self.check_input_cubes(cubes) # Construct graph nodes dictionary graph = { key: [self.queries[key]['succeed'], self.queries[key]['fail']] for key in self.queries.keys() } # Search through tree for all leaves (weather code end points) defined_symbols = [] for item in self.queries.values(): for value in item.values(): if isinstance(value, int): defined_symbols.append(value) # Create symbol cube symbols = self.create_symbol_cube(cubes[0]) # Loop over possible symbols for symbol_code in defined_symbols: # In current decision tree # start node is heavy_precipitation routes = self.find_all_routes(graph, 'heavy_precipitation', symbol_code) # Loop over possible routes from root to leaf for route in routes: conditions = [] for i_node in range(len(route) - 1): current_node = route[i_node] current = copy.copy(self.queries[current_node]) try: next_node = route[i_node + 1] except KeyError: next_node = symbol_code if current['fail'] == next_node: (current['threshold_condition'], current['condition_combination']) = ( self.invert_condition(current)) conditions.extend(self.create_condition_chain(current)) test_chain = self.format_condition_chain(conditions) # Set grid locations to suitable weather symbol symbols.data[np.where(eval(test_chain))] = symbol_code # Update symbols for day or night. symbols = update_daynight(symbols) return symbols