示例#1
0
 def test_process(self):
     """Test that the RecursiveFilter plugin returns the correct data"""
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     result = plugin.process(self.cube, alphas_x=None, alphas_y=None)
     expected = 0.13382206
     self.assertAlmostEqual(result.data[0][2][2], expected)
示例#2
0
 def test_return_type(self):
     """Test that the RecursiveFilter plugin returns an iris.cube.Cube."""
     plugin = RecursiveFilter(alpha_x=self.alpha_x,
                              alpha_y=self.alpha_y,
                              iterations=self.iterations)
     result = plugin.process(self.cube, alphas_x=None, alphas_y=None)
     self.assertIsInstance(result, Cube)
示例#3
0
    def test_different_smoothing_coefficients(self):
        """Test that the _run_recursion method returns expected values when
        smoothing_coefficient values are different in the x and y directions"""
        cube = iris.util.squeeze(self.cube)
        smoothing_coefficient_y = 0.5 * self.smoothing_coefficient_x
        smoothing_coefficients_x = (
            RecursiveFilter()._set_smoothing_coefficients(
                cube, self.smoothing_coefficient_x, None))
        smoothing_coefficients_y = (
            RecursiveFilter()._set_smoothing_coefficients(
                cube, smoothing_coefficient_y, None))
        padded_cube = pad_cube_with_halo(cube, 2, 2)
        result = RecursiveFilter()._run_recursion(padded_cube,
                                                  smoothing_coefficients_x,
                                                  smoothing_coefficients_y, 1)
        # slice back down to the source grid - easier to visualise!
        unpadded_result = result.data[2:-2, 2:-2]

        expected_result = np.array(
            [[0.01620921, 0.02866841, 0.05077430, 0.02881413, 0.01657352],
             [0.03978802, 0.06457599, 0.10290188, 0.06486591, 0.04051282],
             [0.10592333, 0.15184643, 0.19869247, 0.15238355, 0.10726611],
             [0.03978982, 0.06457873, 0.10290585, 0.06486866, 0.04051464],
             [0.01621686, 0.02868005, 0.05079120, 0.02882582, 0.01658128]])

        self.assertArrayAlmostEqual(unpadded_result, expected_result)
示例#4
0
    def test_different_smoothing_coefficients(self):
        """Test that the _run_recursion method returns expected values when
        smoothing_coefficient values are different in the x and y directions"""
        edge_width = 1
        cube = iris.util.squeeze(self.cube)
        smoothing_coefficients_x, smoothing_coefficients_y = RecursiveFilter(
            edge_width=edge_width
        )._pad_coefficients(*self.smoothing_coefficients_alternative)
        padded_cube = pad_cube_with_halo(cube, 2 * edge_width, 2 * edge_width)
        result = RecursiveFilter(edge_width=edge_width)._run_recursion(
            padded_cube, smoothing_coefficients_x, smoothing_coefficients_y, 1
        )
        # slice back down to the source grid - easier to visualise!
        unpadded_result = result.data[2:-2, 2:-2]

        expected_result = np.array(
            [
                [0.01320939, 0.02454378, 0.04346254, 0.02469828, 0.01359563],
                [0.03405095, 0.06060188, 0.09870366, 0.06100013, 0.03504659],
                [0.0845406, 0.13908109, 0.18816182, 0.14006987, 0.08701254],
                [0.03405397, 0.06060749, 0.09871361, 0.06100579, 0.03504971],
                [0.01322224, 0.02456765, 0.04350482, 0.0247223, 0.01360886],
            ],
            dtype=np.float32,
        )
        self.assertArrayAlmostEqual(unpadded_result, expected_result)
示例#5
0
 def test_alphas_shape_does_not_match_data_shape_when_alphas_not_none(self):
     """Test if array dimensions of alphas array do not match dimensions of
        data_array when alphas is not set to None (invalid)."""
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     msg = "Dimensions of alphas array do not match dimensions "
     with self.assertRaisesRegexp(ValueError, msg):
         plugin.set_alphas(self.cube, self.alpha_x, self.alphas_cube2)
 def test_alpha_floats_nan_in_data(self):
     """Test that the RecursiveFilter plugin returns the correct data
     when using float alpha values and the data contains nans."""
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     self.cube.data[0][3][2] = np.nan
     result = plugin.process(self.cube, alphas_x=None, alphas_y=None)
     expected = 0.11979733
     self.assertAlmostEqual(result.data[0][2][2], expected)
示例#7
0
 def test_dimensions_of_output_array_is_as_expected(self):
     """Test that the RecursiveFilter plugin returns a data array with
        the correct dimensions"""
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     result = plugin.process(self.cube, alphas_x=None, alphas_y=None)
     # Output data array should have same dimensions as input data array
     expected_shape = (1, 5, 5)
     self.assertEqual(result.data.shape, expected_shape)
     self.assertEqual(result.data.shape, expected_shape)
示例#8
0
 def test_basic_method(self):
     """Test that the returned recurse_forward_x array has the expected
        type and result."""
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     result = plugin.recurse_forward_x(self.cube.data[0, :],
                                       self.alphas_cube1.data[0, :])
     expected_result = 0.196875
     self.assertIsInstance(result, np.ndarray)
     self.assertAlmostEqual(result[4][2], expected_result)
示例#9
0
 def test_basic_method(self):
     """Test that the returned recurse_backwards_y array has the expected
        type and result."""
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     result = plugin.recurse_backwards_y(self.cube.data[:, 0],
                                         self.alphas_cube1.data[:, 0])
     expected_result = 0.0125
     self.assertIsInstance(result, np.ndarray)
     self.assertAlmostEqual(result[0][0], expected_result)
示例#10
0
 def test_return_type(self):
     """Test that the _run_recursion method returns an iris.cube.Cube."""
     edge_width = 1
     cube = iris.util.squeeze(self.cube)
     alphas_x = RecursiveFilter()._set_alphas(cube, self.alpha_x, None)
     alphas_y = RecursiveFilter()._set_alphas(cube, self.alpha_y, None)
     padded_cube = pad_cube_with_halo(cube, 2 * edge_width, 2 * edge_width)
     result = RecursiveFilter()._run_recursion(padded_cube, alphas_x,
                                               alphas_y, self.iterations)
     self.assertIsInstance(result, Cube)
示例#11
0
 def test_return_type(self):
     """Test that the run_recursion method returns an iris.cube.Cube."""
     edge_width = 1
     alphas_x = RecursiveFilter().set_alphas(self.cube, self.alpha_x, None)
     alphas_y = RecursiveFilter().set_alphas(self.cube, self.alpha_y, None)
     padded_cube = SquareNeighbourhood().pad_cube_with_halo(
         self.cube, edge_width, edge_width)
     result = RecursiveFilter().run_recursion(padded_cube, alphas_x,
                                              alphas_y, self.iterations)
     self.assertIsInstance(result, Cube)
示例#12
0
 def test_expected_result(self):
     """Test that the run_recursion method returns the expected value."""
     edge_width = 1
     alphas_x = RecursiveFilter().set_alphas(self.cube, self.alpha_x, None)
     alphas_y = RecursiveFilter().set_alphas(self.cube, self.alpha_y, None)
     padded_cube = SquareNeighbourhood().pad_cube_with_halo(
         self.cube, edge_width, edge_width)
     result = RecursiveFilter().run_recursion(padded_cube, alphas_x,
                                              alphas_y, self.iterations)
     expected_result = 0.13382206
     self.assertAlmostEqual(result.data[4][4], expected_result)
示例#13
0
 def test_alphas_cube_and_alpha_not_set(self):
     """Test error is raised when both alphas_cube and alpha are set
        to None (invalid)."""
     alpha_x = None
     alpha_y = None
     alphas_cube = None
     plugin = RecursiveFilter(alpha_x=alpha_x, alpha_y=alpha_y,
                              iterations=self.iterations)
     msg = "A value for alpha must be set if alphas_cube is "
     with self.assertRaisesRegexp(ValueError, msg):
         plugin.set_alphas(self.cube, alpha_x, alphas_cube)
示例#14
0
 def test_result_basic(self):
     """Test that the _run_recursion method returns the expected value."""
     edge_width = 1
     cube = iris.util.squeeze(self.cube)
     alphas_x = RecursiveFilter()._set_alphas(cube, self.alpha_x, None)
     alphas_y = RecursiveFilter()._set_alphas(cube, self.alpha_y, None)
     padded_cube = pad_cube_with_halo(cube, 2 * edge_width, 2 * edge_width)
     result = RecursiveFilter()._run_recursion(padded_cube, alphas_x,
                                               alphas_y, self.iterations)
     expected_result = 0.13382206
     self.assertAlmostEqual(result.data[4][4], expected_result)
示例#15
0
 def test_alphas_array_as_expected_when_alphas_is_not_none(self):
     """Test that the returned alphas array has the expected result
        when alphas=None."""
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     result = plugin.set_alphas(self.cube, self.alpha_x, self.alphas_cube1)
     expected_result = 0.5
     self.assertIsInstance(result.data, np.ndarray)
     self.assertEqual(result.data[0][2], expected_result)
     # Check shape: Array should be padded with 4 extra rows/columns
     expected_shape = (9, 9)
     self.assertEqual(result.shape, expected_shape)
 def test_alpha_cubes_masked_data(self):
     """Test that the RecursiveFilter plugin returns the correct data
     when using alpha cubes and a masked data cube."""
     plugin = RecursiveFilter(alpha_x=None, alpha_y=None,
                              iterations=self.iterations)
     mask = np.zeros((self.cube.data.shape))
     mask[0][3][2] = 1
     self.cube.data = np.ma.MaskedArray(self.cube.data, mask=mask)
     result = plugin.process(self.cube, alphas_x=self.alphas_cube,
                             alphas_y=self.alphas_cube)
     expected = 0.11979733
     self.assertAlmostEqual(result.data[0][2][2], expected)
 def test_alpha_floats_nan_in_masked_data(self):
     """Test that the RecursiveFilter plugin returns the correct data
     when using float alpha values, the data contains nans and the data
     is masked (but not the nan value)."""
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     self.cube.data[0][3][2] = np.nan
     mask = np.zeros((self.cube.data.shape))
     mask[0][1][2] = 1
     self.cube.data = np.ma.MaskedArray(self.cube.data, mask=mask)
     result = plugin.process(self.cube, alphas_x=None, alphas_y=None)
     expected = 0.105854129
     self.assertAlmostEqual(result.data[0][2][2], expected)
示例#18
0
 def test_basic(self):
     """Test that the run_recursion method returns an iris.cube.Cube."""
     edge_width = 1
     alphas_x = None
     alphas_y = None
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     alphas_x = plugin.set_alphas(self.cube, self.alpha_x, alphas_x)
     alphas_y = plugin.set_alphas(self.cube, self.alpha_y, alphas_y)
     padded_cube = SquareNeighbourhood().pad_cube_with_halo(self.cube,
                                                            edge_width,
                                                            edge_width)
     result = plugin.run_recursion(padded_cube, alphas_x, alphas_y,
                                   self.iterations)
     self.assertIsInstance(result, Cube)
示例#19
0
 def test_return_type(self):
     """Test that the _run_recursion method returns an iris.cube.Cube."""
     edge_width = 1
     cube = iris.util.squeeze(self.cube)
     smoothing_coefficients_x, smoothing_coefficients_y = RecursiveFilter(
         edge_width=edge_width
     )._pad_coefficients(*self.smoothing_coefficients)
     padded_cube = pad_cube_with_halo(cube, 2 * edge_width, 2 * edge_width)
     result = RecursiveFilter(edge_width=1)._run_recursion(
         padded_cube,
         smoothing_coefficients_x,
         smoothing_coefficients_y,
         self.iterations,
     )
     self.assertIsInstance(result, Cube)
示例#20
0
 def test_smoothing_coefficient_y_lt_zero(self):
     """Test when an smoothing_coefficient_y value <= zero is given
     (invalid)."""
     smoothing_coefficient_y = -0.5
     msg = "Invalid smoothing_coefficient_y: must be > 0 and <= 0.5: -0.5"
     with self.assertRaisesRegex(ValueError, msg):
         RecursiveFilter(smoothing_coefficient_y=smoothing_coefficient_y)
示例#21
0
 def test_result_basic(self):
     """Test that the _run_recursion method returns the expected value."""
     edge_width = 1
     cube = iris.util.squeeze(self.cube)
     smoothing_coefficients_x, smoothing_coefficients_y = RecursiveFilter(
         edge_width=edge_width
     )._pad_coefficients(*self.smoothing_coefficients)
     padded_cube = pad_cube_with_halo(cube, 2 * edge_width, 2 * edge_width)
     result = RecursiveFilter(edge_width=edge_width)._run_recursion(
         padded_cube,
         smoothing_coefficients_x,
         smoothing_coefficients_y,
         self.iterations,
     )
     expected_result = 0.12302627
     self.assertAlmostEqual(result.data[4][4], expected_result)
示例#22
0
 def test_smoothing_coefficients_mismatched_y_points(self):
     """Test that an error is raised if the y smoothing_coefficients_cube
     has mismatched coordinate points compared to the data cube."""
     msg = "The points of the y spatial dimension of the smoothing coefficients"
     with self.assertRaisesRegex(ValueError, msg):
         RecursiveFilter(edge_width=1)._validate_smoothing_coefficients(
             self.cube, self.smoothing_coefficients_cube_wrong_y_points)
示例#23
0
 def test_alphas_cube_and_alpha_both_set(self):
     """Test error is raised when both alphas_cube and alpha are set."""
     alpha = 0.5
     alphas_cube = self.alphas_cube
     msg = "A cube of alpha values and a single float value for"
     with self.assertRaisesRegex(ValueError, msg):
         RecursiveFilter()._set_alphas(self.cube, alpha, alphas_cube)
示例#24
0
 def test_mismatched_dimensions_alphas_cube_data_cube(self):
     """Test that an error is raised if the alphas_cube is of a different
     shape to the data cube."""
     msg = "Dimensions of alphas array do not match dimensions "
     with self.assertRaisesRegex(ValueError, msg):
         RecursiveFilter()._set_alphas(self.cube, None,
                                       self.alphas_cube_wrong_dims)
示例#25
0
def process(
    cube: cli.inputcube,
    smoothing_coefficients: cli.inputcubelist,
    *,
    iterations: int = 1,
):
    """Module to apply a recursive filter to neighbourhooded data.

    Run a recursive filter to convert a square neighbourhood into a
    Gaussian-like kernel or smooth over short distances. The filter uses a
    smoothing_coefficient (between 0 and 1) to control what proportion of the
    probability is passed onto the next grid-square in the x and y directions.
    The smoothing_coefficient can be set on a grid square by grid-square basis
    for the x and y directions separately (using two arrays of
    smoothing_coefficients of the same dimensionality as the domain).

    Args:
        cube (iris.cube.Cube):
            Cube to be processed.
        smoothing_coefficients (iris.cube.CubeList):
            CubeList describing the smoothing_coefficients to be used in the x
            and y directions.
        iterations (int):
            Number of times to apply the filter. (Typically < 3)
            Number of iterations should be 2 or less, higher values have been
            shown to lead to poorer conservation.

    Returns:
        iris.cube.Cube:
            The processed Cube.
    """
    from improver.nbhood.recursive_filter import RecursiveFilter

    plugin = RecursiveFilter(iterations=iterations)
    return plugin(cube, smoothing_coefficients=smoothing_coefficients)
示例#26
0
 def test_expected_result(self):
     """Test that the run_recursion method returns an iris.cube.Cube."""
     edge_width = 1
     alphas_x = None
     alphas_y = None
     plugin = RecursiveFilter(alpha_x=self.alpha_x, alpha_y=self.alpha_y,
                              iterations=self.iterations)
     alphas_x = plugin.set_alphas(self.cube, self.alpha_x, alphas_x)
     alphas_y = plugin.set_alphas(self.cube, self.alpha_y, alphas_y)
     padded_cube = SquareNeighbourhood().pad_cube_with_halo(self.cube,
                                                            edge_width,
                                                            edge_width)
     result = plugin.run_recursion(padded_cube, alphas_x, alphas_y,
                                   self.iterations)
     expected_result = 0.13382206
     self.assertAlmostEqual(result.data[4][4], expected_result)
示例#27
0
    def test_coordinate_reordering_with_different_smoothing_coefficients(self):
        """Test that x and y smoothing_coefficients still apply to the right
        coordinate when the input cube spatial dimensions are (x, y) not
        (y, x)"""
        enforce_coordinate_ordering(self.cube, ["realization", "longitude", "latitude"])
        plugin = RecursiveFilter(iterations=self.iterations,)
        result = plugin(
            self.cube, smoothing_coefficients=self.smoothing_coefficients_alternative
        )

        expected_result = np.array(
            [
                [0.02554158, 0.05397786, 0.1312837, 0.05397786, 0.02554158],
                [0.03596632, 0.07334216, 0.1668669, 0.07334216, 0.03596632],
                [0.05850913, 0.11031596, 0.21073693, 0.11031596, 0.05850913],
                [0.03596632, 0.07334216, 0.1668669, 0.07334216, 0.03596632],
                [0.02554158, 0.05397786, 0.1312837, 0.05397786, 0.02554158],
            ],
            dtype=np.float32,
        )

        self.assertSequenceEqual(
            [x.name() for x in result.coords(dim_coords=True)],
            ["realization", "longitude", "latitude"],
        )
        self.assertArrayAlmostEqual(result.data[0], expected_result)
示例#28
0
 def test_alpha_y_gt_unity(self):
     """Test when an alpha_y value > unity is given (invalid)."""
     alpha_y = 1.1
     msg = "Invalid alpha_y: must be >= 0 and < 1: 1.1"
     with self.assertRaisesRegexp(ValueError, msg):
         RecursiveFilter(alpha_x=None, alpha_y=alpha_y,
                         iterations=None, edge_width=1)
示例#29
0
 def test_alpha_y_lt_zero(self):
     """Test when an alpha_y value < zero is given (invalid)."""
     alpha_y = -0.5
     msg = "Invalid alpha_y: must be >= 0 and < 1: -0.5"
     with self.assertRaisesRegexp(ValueError, msg):
         RecursiveFilter(alpha_x=None, alpha_y=alpha_y,
                         iterations=None, edge_width=1)
示例#30
0
 def test_iterations(self):
     """Test when iterations value less than unity is given (invalid)."""
     iterations = 0
     msg = "Invalid number of iterations: must be >= 1: 0"
     with self.assertRaisesRegexp(ValueError, msg):
         RecursiveFilter(alpha_x=None, alpha_y=None,
                         iterations=iterations, edge_width=1)