Beispiel #1
0
 def test_fails_coord_not_in_cube(self):
     """Test it raises CoordinateNotFoundError if coord not in the cube."""
     coord = "notset"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     msg = ('Expected to find exactly 1  coordinate, but found none.')
     with self.assertRaisesRegexp(CoordinateNotFoundError, msg):
         plugin.process(self.cube)
Beispiel #2
0
 def test_fails_coord_not_in_cube(self):
     """Test it raises CoordinateNotFoundError if coord not in the cube."""
     coord = "notset"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     msg = ('Coordinate to be collapsed not found in cube.')
     with self.assertRaisesRegex(CoordinateNotFoundError, msg):
         plugin.process(self.cube)
Beispiel #3
0
 def test_fails_input_not_a_cube(self):
     """Test it raises a Type Error if not supplied with a cube."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     notacube = 0.0
     msg = ('The first argument must be an instance of ' + 'iris.cube.Cube')
     with self.assertRaisesRegexp(TypeError, msg):
         plugin.process(notacube)
 def test_fails_coord_not_in_weights_cube(self):
     """Test it raises CoordinateNotFoundError if the blending coord is not
     found in the weights cube."""
     coord = "forecast_reference_time"
     self.weights1d.remove_coord("forecast_reference_time")
     plugin = WeightedBlendAcrossWholeDimension(coord)
     msg = ('Coordinate to be collapsed not found in weights cube.')
     with self.assertRaisesRegex(CoordinateNotFoundError, msg):
         plugin.process(self.cube, self.weights1d)
Beispiel #5
0
 def test_forecast_reference_time_exception(self):
     """Test that a ValueError is raised if the coordinate to be blended
     is forecast_reference_time and the points on the time coordinate are
     not equal."""
     coord = "forecast_reference_time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     msg = ('For blending using the forecast_reference_time')
     with self.assertRaisesRegexp(ValueError, msg):
         plugin.process(self.cube)
Beispiel #6
0
 def test_fails_more_than_one_perc_coord(self):
     """Test it raises a Value Error if more than one percentile coord."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     new_cube = percentile_cube()
     new_cube.add_aux_coord(
         AuxCoord([10.0], long_name="percentile_over_dummy"))
     msg = ('There should only be one percentile coord ' 'on the cube.')
     with self.assertRaisesRegexp(ValueError, msg):
         plugin.process(new_cube)
Beispiel #7
0
 def test_fails_weights_shape(self):
     """Test it raises a Value Error if weights shape does not match
        coord shape."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     weights = [0.1, 0.2, 0.7]
     msg = ('The weights array must match the shape ' +
            'of the coordinate in the input cube')
     with self.assertRaisesRegexp(ValueError, msg):
         plugin.process(self.cube, weights)
Beispiel #8
0
 def test_fails_perc_coord_not_dim(self):
     """Test it raises a Value Error if not percentile coord not a dim."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     new_cube = self.cube.copy()
     new_cube.add_aux_coord(
         AuxCoord([10.0], long_name="percentile_over_time"))
     msg = ('The percentile coord must be a dimension ' 'of the cube.')
     with self.assertRaisesRegexp(ValueError, msg):
         plugin.process(new_cube)
 def test_scalar_coord(self):
     """Test plugin throws an error if trying to blending across a scalar
     coordinate."""
     coord = "dummy_scalar_coord"
     new_scalar_coord = AuxCoord(1, long_name=coord, units='no_unit')
     self.cube.add_aux_coord(new_scalar_coord)
     plugin = WeightedBlendAcrossWholeDimension(coord)
     weights = ([1.0])
     msg = 'has no associated dimension'
     with self.assertRaisesRegex(ValueError, msg):
         plugin.process(self.cube, weights)
Beispiel #10
0
 def test_fails_only_one_percentile_value(self):
     """Test it raises a Value Error if there is only one percentile."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     new_cube = Cube([[0.0]])
     new_cube.add_dim_coord(
         DimCoord([10.0], long_name="percentile_over_time"), 0)
     new_cube.add_dim_coord(DimCoord([10.0], long_name="time"), 1)
     msg = ('Percentile coordinate does not have enough points'
            ' in order to blend. Must have at least 2 percentiles.')
     with self.assertRaisesRegexp(ValueError, msg):
         plugin.process(new_cube)
    def test_specific_cycletime(self):
        """Test that the plugin setup with a specific cycletime returns a cube
        in which the forecast reference time has been changed to match the
        given cycletime. The forecast period should also have been adjusted to
        be given relative to this time.

        For this we need a single time in our cube and so to blend over
        something else. In this case we create a "model_id" coordinate as if we
        are model blending."""

        coord_name = "model_id"

        cube1 = self.cube[0].copy()
        model_crd1 = iris.coords.DimCoord([0], long_name=coord_name, units=1)
        cube1.add_aux_coord(model_crd1)

        cube2 = self.cube[0].copy()
        model_crd2 = iris.coords.DimCoord([1], long_name=coord_name, units=1)
        cube2.add_aux_coord(model_crd2)

        cubes = iris.cube.CubeList([cube1, cube2])
        cube = merge_cubes(cubes)

        plugin = WeightedBlendAcrossWholeDimension(coord_name)
        expected_frt = 1447837200
        expected_forecast_period = 61200
        result = plugin.process(cube, cycletime='20151118T0900Z')

        self.assertEqual(
            result.coord('forecast_reference_time').points, expected_frt)
        self.assertEqual(
            result.coord('forecast_period').points, expected_forecast_period)
        self.assertEqual(
            result.coord('time').points,
            cube.coord('time').points)
Beispiel #12
0
 def test_coord_adjust_set(self):
     """Test it works with coord adjust set."""
     coord = "time"
     coord_adjust = example_coord_adjust
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean',
                                                coord_adjust)
     result = plugin.process(self.cube)
     self.assertAlmostEquals(result.coord(coord).points, [402193.5])
Beispiel #13
0
 def test_weights_equal_array(self):
     """Test it works with weights set to array (0.8, 0.2)."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     weights = np.array([0.8, 0.2])
     result = plugin.process(self.cube, weights)
     expected_result_array = np.ones((2, 2)) * 1.2
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Beispiel #14
0
 def test_weighted_max_weights_none(self):
     """Test it works for weighted max with weights set to None."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_maximum')
     weights = None
     result = plugin.process(self.cube, weights)
     expected_result_array = np.ones((2, 2))
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Beispiel #15
0
 def tests_threshold_splicing_works_weighted_max(self):
     """Test weighted_max works with a threshold dimension."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_maximum')
     weights = np.array([0.8, 0.2])
     result = plugin.process(self.cube_threshold, weights)
     expected_result_array = np.ones((2, 2, 2)) * 0.4
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Beispiel #16
0
 def test_percentiles_weights_none(self):
     """Test it works for percentiles with weights set to None."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     weights = None
     perc_cube = percentile_cube()
     result = plugin.process(perc_cube, weights)
     expected_result_array = np.reshape(BLENDED_PERCENTILE_DATA1, (6, 2, 2))
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Beispiel #17
0
 def test_percentiles_different_coordinate_orders(self):
     """Test the result of the percentile aggregation is the same
     regardless of the coordinate order in the input cube. Most
     importantly, the result should be the same regardless of on which
     side of the collapsing coordinate the percentile coordinate falls."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     weights = None
     percentile_leading = percentile_cube()
     time_leading = percentile_cube()
     time_leading.transpose([1, 0, 2, 3])
     result_percentile_leading = plugin.process(percentile_leading, weights)
     result_time_leading = plugin.process(time_leading, weights)
     expected_result_array = np.reshape(BLENDED_PERCENTILE_DATA1, (6, 2, 2))
     self.assertArrayAlmostEqual(result_percentile_leading.data,
                                 expected_result_array)
     self.assertArrayAlmostEqual(result_time_leading.data,
                                 expected_result_array)
Beispiel #18
0
 def test_weighted_max_non_equal_weights_array(self):
     """Test it works for weighted_max with weights [0.2, 0.8]
        given as a array."""
     coord = "time"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_maximum')
     weights = np.array([0.2, 0.8])
     result = plugin.process(self.cube, weights)
     expected_result_array = np.ones((2, 2)) * 1.6
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Beispiel #19
0
    def test_scalar_coord(self):
        """Test plugin throws an error if trying to blending across a scalar
        coordinate."""

        coord = "dummy_scalar_coord"
        plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
        weights = ([1.0])
        msg = 'has no associated dimension'
        with self.assertRaisesRegex(ValueError, msg):
            _ = plugin.process(self.cube_with_scalar, weights)
Beispiel #20
0
 def tests_threshold_splicing_works_with_threshold(self):
     """Test splicing works when the blending is over threshold."""
     coord = "threshold"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     weights = np.array([0.8, 0.2])
     self.cube_threshold.data[0, :, :, :] = 0.5
     self.cube_threshold.data[1, :, :, :] = 0.8
     result = plugin.process(self.cube_threshold, weights)
     expected_result_array = np.ones((2, 2, 2)) * 0.56
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Beispiel #21
0
    def test_alternative_title(self):
        """Test that the plugin returns an iris.cube.Cube with metadata that
        matches the input cube where appropriate. In this case the title is
        removed from the input cube, resulting in a default title being applied
        to the result cube."""

        coord = "forecast_reference_time"
        plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
        self.cube.attributes.pop('title')
        expected = "IMPROVER Model Forecast"
        result = plugin.process(self.cube)

        self.assertEqual(result.attributes['title'], expected)
Beispiel #22
0
 def test_source_realizations_attribute_added(self):
     """Test that when a realization coordinate is collapsed, a new
     source_realizations attribute is added to record the contributing
     realizations."""
     coord = "realization"
     self.cube.coord('time').rename(coord)
     self.cube.coord(coord).points = [1, 4]
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     weights = None
     result = plugin.process(self.cube, weights)
     expected = [1, 4]
     self.assertArrayEqual(result.attributes['source_realizations'],
                           expected)
 def test_cycletime_not_updated(self):
     """Test changes to forecast period and forecast reference time are not
     made when not blending over cycle or model."""
     cube = set_up_variable_cube(278 * np.ones((3, 5, 5), dtype=np.float32),
                                 time=datetime(2019, 10, 11, 1),
                                 frt=datetime(2019, 10, 10, 21))
     expected_frt = cube.coord("forecast_reference_time").points[0]
     expected_fp = cube.coord("forecast_period").points[0]
     plugin = WeightedBlendAcrossWholeDimension("realization")
     result = plugin.process(cube, cycletime='20191011T0000Z')
     self.assertEqual(
         result.coord("forecast_reference_time").points[0], expected_frt)
     self.assertEqual(
         result.coord("forecast_period").points[0], expected_fp)
Beispiel #24
0
 def test_scalar_coord(self, warning_list=None):
     """Test it works on scalar coordinate
        and check that a warning has been raised
        if the dimension that you want to blend on
        is a scalar coordinate.
     """
     coord = "dummy_scalar_coord"
     plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_mean')
     weights = np.array([1.0])
     result = plugin.process(self.cube_with_scalar, weights)
     self.assertTrue(
         any(item.category == UserWarning for item in warning_list))
     warning_msg = "Trying to blend across a scalar coordinate"
     self.assertTrue(any(warning_msg in str(item) for item in warning_list))
     self.assertArrayAlmostEqual(result.data, self.cube.data)
 def test_attributes_dict(self):
     """Test updates to attributes on output cube"""
     attributes_dict = {"source": "IMPROVER", "history": "cycle blended"}
     for key in self.cube.attributes:
         if "mosg__" in key:
             attributes_dict[key] = "remove"
     expected_attributes = {
         "source": "IMPROVER",
         "history": "cycle blended",
         "title": self.cube.attributes["title"],
         "institution": MANDATORY_ATTRIBUTE_DEFAULTS["institution"]
     }
     coord = "forecast_reference_time"
     plugin = WeightedBlendAcrossWholeDimension(coord)
     result = plugin.process(self.cube, attributes_dict=attributes_dict)
     self.assertDictEqual(result.attributes, expected_attributes)
    def process(self, cube):
        """
        Apply the weighted blend for each point in the given coordinate.

        Args:
            cube : iris.cube.Cube
                Cube to blend.

        Returns:
            cube: iris.cube.Cube
                The processed cube, with the same coordinates as the input
                cube. The points in one coordinate will be blended with the
                adjacent points based on a triangular weighting function of the
                specified width.

        """
        # We need to correct all the coordinates associated with the dimension
        # we are collapsing over, so find the relevant coordinates now.
        dimension_to_collapse = cube.coord_dims(self.coord)
        coords_to_correct = cube.coords(dimensions=dimension_to_collapse)
        coords_to_correct = [coord.name() for coord in coords_to_correct]
        # We will also need to correct the bounds on these coordinates,
        # as bounds will be added when the blending happens, so add bounds if
        # it doesn't have some already.
        for coord in coords_to_correct:
            if not cube.coord(coord).has_bounds():
                cube.coord(coord).guess_bounds()
        # Set up a plugin to calculate the triangular weights.
        WeightsPlugin = ChooseDefaultWeightsTriangular(
            self.width, units=self.parameter_units)
        # Set up the blending function, based on whether weighted blending or
        # maximum probabilities are needed.
        BlendingPlugin = WeightedBlendAcrossWholeDimension(self.coord,
                                                           self.mode)
        result = iris.cube.CubeList([])
        # Loop over each point in the coordinate we are blending over, and
        # calculate a new weighted average for it.
        for cube_slice in cube.slices_over(self.coord):
            point = cube_slice.coord(self.coord).points[0]
            weights = WeightsPlugin.process(cube, self.coord, point)
            blended_cube = BlendingPlugin.process(cube, weights)
            self.correct_collapsed_coordinates(cube_slice, blended_cube,
                                               coords_to_correct)
            result.append(blended_cube)
        result = concatenate_cubes(result)
        return result
    def test_basic(self):
        """Test that the plugin returns an iris.cube.Cube with metadata that
        matches the input cube where appropriate."""
        coord = "forecast_reference_time"
        plugin = WeightedBlendAcrossWholeDimension(coord)
        result = plugin.process(self.cube)

        expected_frt = int(
            self.cube.coord('forecast_reference_time').points[-1])
        expected_forecast_period = int(
            self.cube.coord('forecast_period').points[-1])

        self.assertIsInstance(result, Cube)
        self.assertEqual(result.attributes, self.expected_attributes)
        self.assertEqual(
            result.coord('forecast_reference_time').points, expected_frt)
        self.assertEqual(
            result.coord('forecast_period').points, expected_forecast_period)
 def test_remove_unnecessary_scalar_coordinates(self):
     """Test model_id and model_configuration coordinates are both removed
     after model blending"""
     cube_model = set_up_variable_cube(282 * np.zeros(
         (2, 2), dtype=np.float32))
     cube_model = add_coordinate(cube_model, [0, 1], "model_id")
     cube_model.add_aux_coord(AuxCoord(["uk_ens", "uk_det"],
                                       long_name="model_configuration"),
                              data_dims=0)
     weights_model = Cube(np.array([0.5, 0.5]),
                          long_name='weights',
                          dim_coords_and_dims=[
                              (cube_model.coord("model_id"), 0)
                          ])
     plugin = WeightedBlendAcrossWholeDimension("model_id")
     result = plugin.process(cube_model, weights_model)
     for coord_name in ["model_id", "model_configuration"]:
         self.assertNotIn(coord_name,
                          [coord.name() for coord in result.coords()])
Beispiel #29
0
    def tests_threshold_cube_with_weights_weighted_maximum(self):
        """Test weighted_maximum works collapsing a cube with a threshold
        dimension when the blending is over a different coordinate."""
        coord = "forecast_reference_time"
        plugin = WeightedBlendAcrossWholeDimension(coord, 'weighted_maximum')
        result = plugin.process(self.cube_threshold, self.weights1d)
        expected_result_array = np.ones((2, 2, 2)) * 0.12
        expected_result_array[1, :, :] = 0.24

        expected_frt = int(
            self.cube.coord('forecast_reference_time').points[-1])
        expected_forecast_period = int(
            self.cube.coord('forecast_period').points[-1])

        self.assertArrayAlmostEqual(result.data, expected_result_array)
        self.assertEqual(result.attributes, self.attributes)
        self.assertEqual(result.coord('time').points, expected_frt)
        self.assertEqual(
            result.coord('forecast_period').points, expected_forecast_period)
    def test_threshold_cube_with_weights_weighted_mean(self):
        """Test weighted_mean method works collapsing a cube with a threshold
        dimension when the blending is over a different coordinate. Note that
        this test is in process to include the slicing."""
        coord = "forecast_reference_time"
        plugin = WeightedBlendAcrossWholeDimension(coord)
        result = plugin.process(self.cube_threshold, self.weights1d)
        expected_result_array = np.ones((2, 2, 2)) * 0.3
        expected_result_array[1, :, :] = 0.5

        expected_frt = int(
            self.cube.coord('forecast_reference_time').points[-1])
        expected_forecast_period = int(
            self.cube.coord('forecast_period').points[-1])

        self.assertArrayAlmostEqual(result.data, expected_result_array)
        self.assertEqual(result.attributes, self.expected_attributes)
        self.assertEqual(result.coord('time').points, expected_frt)
        self.assertEqual(
            result.coord('forecast_period').points, expected_forecast_period)