Esempio n. 1
0
 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)
Esempio n. 2
0
    def test_wxcode_updated_on_latlon(self):
        """Test Correct wxcodes returned for lat lon cube."""
        cube = set_up_wxcube(lat_lon=True)
        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)
Esempio n. 3
0
    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."""
        cube = set_up_wxcube(time=datetime.datetime(2018, 9, 12, 5, 42, 59))
        cube.data = self.cube_data
        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))
Esempio n. 4
0
 def test_wxcode_updated(self):
     """Test Correct wxcodes returned for cube."""
     cube = set_up_wxcube()
     cube.data = self.cube_data
     # Only 1,3,10, 14, 17, 20, 23, 26 and 29 change from day to night
     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.shape, (16, 16))
Esempio n. 5
0
    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))
Esempio n. 6
0
    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))
Esempio n. 7
0
 def test_basic_lat_lon(self):
     """Test that the function returns a weather code lat lon cube.."""
     cube = set_up_wxcube(lat_lon=True)
     result = update_daynight(cube)
     self.assertIsInstance(result, iris.cube.Cube)
     self.assertEqual(result.name(), "weather_code")
     self.assertEqual(result.units, "1")
     self.assertArrayEqual(result.attributes["weather_code"], self.wxcode)
     self.assertEqual(result.attributes["weather_code_meaning"], self.wxmeaning)
Esempio n. 8
0
 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)
Esempio n. 9
0
 def test_basic(self):
     """Test that the function returns a weather code cube."""
     cube = set_up_wxcube()
     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)
Esempio n. 10
0
 def test_wxcode_time_as_array(self):
     """ Test code works if time is an array of dimension > 1 """
     cube = set_up_wxcube(time_points=[
         datetime.datetime(2018, 9, 12, 5),
         datetime.datetime(2018, 9, 12, 6),
         datetime.datetime(2018, 9, 12, 7),
     ])
     expected_result = np.ones((3, 16, 16))
     expected_result[0, :, :] = 0
     result = update_daynight(cube)
     self.assertArrayEqual(result.data, expected_result)
Esempio n. 11
0
 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)
Esempio n. 12
0
    def test_wxcode_time_as_array(self):
        """ Test code works if time is an array of dimension > 1 """
        time_points = [
            datetime.datetime(2018, 9, 12, 5),
            datetime.datetime(2018, 9, 12, 6),
            datetime.datetime(2018, 9, 12, 7),
        ]
        cubes = iris.cube.CubeList()
        for time in time_points:
            cubes.append(set_up_wxcube(time=time))
        cube = cubes.merge_cube()

        expected_result = np.ones((3, 16, 16))
        expected_result[0, :, :] = 0
        result = update_daynight(cube)
        self.assertArrayEqual(result.data, expected_result)
Esempio n. 13
0
    def process(self, cubes: CubeList) -> Cube:
        """Apply the decision tree to the input cubes to produce weather
        symbol output.

        Args:
            cubes:
                A cubelist containing the diagnostics required for the
                weather symbols decision tree, these at co-incident times.

        Returns:
            A cube of weather symbols.
        """
        # Check input cubes contain required data
        optional_node_data_missing = self.check_input_cubes(cubes)
        # Construct graph nodes dictionary
        graph = {
            key: [self.queries[key]["succeed"], self.queries[key]["fail"]]
            for key in self.queries
        }
        # 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)
        # 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,
                self.start_node,
                symbol_code,
                omit_nodes=optional_node_data_missing,
            )
            # 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.append(self.create_condition_chain(current))
                test_chain = [conditions, "AND"]

                # Set grid locations to suitable weather symbol
                symbols.data[
                    np.ma.where(self.evaluate_condition_chain(cubes, test_chain))
                ] = symbol_code
        # Update symbols for day or night.
        symbols = update_daynight(symbols)
        return symbols