class Test_gradient_from_diff(IrisTest):

    """Test for correct behaviour when calculating a gradient"""

    def setUp(self):
        """Set up cube."""
        data = np.array([[1, 2, 3],
                         [2, 4, 2],
                         [5, 10, 15]])
        x_coord = DimCoord(2.*np.arange(3), "projection_x_coordinate")
        y_coord = DimCoord(2.*np.arange(3), "projection_y_coordinate")
        self.cube = iris.cube.Cube(data, "wind_speed", units="m s-1",
                                   dim_coords_and_dims=[(y_coord, 0),
                                                        (x_coord, 1)])
        self.plugin = DifferenceBetweenAdjacentGridSquares(gradient=True)

    def test_basic(self):
        """Test contents and metadata"""
        expected = np.array([[0.5, 0.5, 0.5],
                             [2.0, 0.0, -2.0],
                             [2.5, 2.5, 2.5]])
        xdiff = self.plugin.calculate_difference(self.cube, "x")
        result = self.plugin.gradient_from_diff(xdiff, self.cube, "x")
        self.assertArrayAlmostEqual(result.data, expected)
        self.assertEqual(result.name(), "gradient_of_wind_speed")
예제 #2
0
class Test_process(IrisTest):

    """Test the process method."""

    def setUp(self):
        """Set up cube."""
        data = np.array([[1, 2, 3], [2, 4, 6], [5, 10, 15]])
        self.cube = set_up_cube(data, "wind_speed", "m s-1")
        self.plugin = DifferenceBetweenAdjacentGridSquares()

    def test_basic(self):
        """Test that differences are calculated along both the x and
        y dimensions and returned as separate cubes."""
        expected_x = np.array([[1, 1], [2, 2], [5, 5]])
        expected_y = np.array([[1, 2, 3], [3, 6, 9]])
        result = self.plugin.process(self.cube)
        self.assertIsInstance(result[0], Cube)
        self.assertArrayAlmostEqual(result[0].data, expected_x)
        self.assertIsInstance(result[1], Cube)
        self.assertArrayAlmostEqual(result[1].data, expected_y)

    def test_3d_cube(self):
        """Test the differences are calculated along both the x and
        y dimensions and returned as separate cubes when a 3d cube is input."""
        data = np.array(
            [[[1, 2, 3], [2, 4, 6], [5, 10, 15]], [[1, 2, 3], [2, 2, 6], [5, 10, 20]]]
        )
        expected_x = np.array([[[1, 1], [2, 2], [5, 5]], [[1, 1], [0, 4], [5, 10]]])
        expected_y = np.array([[[1, 2, 3], [3, 6, 9]], [[1, 0, 3], [3, 8, 14]]])
        cube = set_up_cube(data, "wind_speed", "m s-1", realizations=np.array([1, 2]))
        result = self.plugin.process(cube)
        self.assertIsInstance(result[0], iris.cube.Cube)
        self.assertArrayAlmostEqual(result[0].data, expected_x)
        self.assertIsInstance(result[1], iris.cube.Cube)
        self.assertArrayAlmostEqual(result[1].data, expected_y)
 def setUp(self):
     """Set up cube."""
     data = np.array([[1, 2, 3],
                      [2, 4, 6],
                      [5, 10, 15]])
     self.cube = set_up_cube(data, "wind_speed", "m s-1")
     self.plugin = DifferenceBetweenAdjacentGridSquares()
class Test_calculate_difference(IrisTest):

    """Test the calculate_difference method."""

    def setUp(self):
        """Set up cube."""
        data = np.array([[1, 2, 3],
                         [2, 4, 6],
                         [5, 10, 15]])
        self.cube = set_up_cube(data, "wind_speed", "m s-1")
        self.plugin = DifferenceBetweenAdjacentGridSquares()

    def test_x_dimension(self):
        """Test differences calculated along the x dimension."""
        expected = np.array([[1, 1],
                             [2, 2],
                             [5, 5]])
        result = self.plugin.calculate_difference(self.cube, "x")
        self.assertIsInstance(result, Cube)
        self.assertArrayAlmostEqual(result.data, expected)

    def test_y_dimension(self):
        """Test differences calculated along the y dimension."""
        expected = np.array([[1, 2, 3],
                             [3, 6, 9]])
        result = self.plugin.calculate_difference(self.cube, "y")
        self.assertIsInstance(result, Cube)
        self.assertArrayAlmostEqual(result.data, expected)

    def test_missing_data(self):
        """Test that the result is as expected when data is missing."""
        data = np.array([[1, 2, 3],
                         [np.nan, 4, 6],
                         [5, 10, 15]])
        cube = set_up_cube(data, "wind_speed", "m s-1")
        expected = np.array([[np.nan, 2, 3],
                             [np.nan, 6, 9]])
        result = self.plugin.calculate_difference(cube, "y")
        self.assertIsInstance(result, Cube)
        self.assertArrayAlmostEqual(result.data, expected)

    def test_masked_data(self):
        """Test that the result is as expected when data is masked."""
        data = ma.array([[1, 2, 3],
                         [2, 4, 6],
                         [5, 10, 15]],
                        mask=[[0, 0, 0],
                              [1, 0, 0],
                              [0, 0, 0]])
        cube = set_up_cube(data, "wind_speed", "m s-1")
        expected = ma.array([[1, 2, 3],
                             [3, 6, 9]],
                            mask=[[1, 0, 0],
                                  [1, 0, 0]])
        result = self.plugin.calculate_difference(cube, "y")
        self.assertIsInstance(result, Cube)
        self.assertArrayEqual(result.data, expected)
        self.assertArrayEqual(result.data.mask, expected.mask)
예제 #5
0
class Test_create_difference_cube(IrisTest):

    """Test the create_difference_cube method."""

    def setUp(self):
        """Set up cube."""
        data = np.array([[1, 2, 3],
                         [2, 4, 6],
                         [5, 10, 15]])
        self.cube = set_up_cube(data, "wind_speed", "m s-1")
        self.plugin = DifferenceBetweenAdjacentGridSquares()

    def test_y_dimension(self):
        """Test differences calculated along the y dimension."""
        diff_array = np.array([[1, 2, 3],
                               [3, 6, 9]])
        result = self.plugin.create_difference_cube(
            self.cube, "projection_y_coordinate", diff_array)
        self.assertIsInstance(result, Cube)
        self.assertArrayAlmostEqual(result.data, diff_array)

    def test_x_dimension(self):
        """Test differences calculated along the x dimension."""
        diff_array = np.array([[1, 1],
                               [2, 2],
                               [5, 5]])
        result = self.plugin.create_difference_cube(
            self.cube, "projection_x_coordinate", diff_array)
        self.assertIsInstance(result, Cube)
        self.assertArrayAlmostEqual(result.data, diff_array)

    def test_metadata(self):
        """Test that the result has the expected metadata."""
        diff_array = np.array([[1, 2, 3],
                               [3, 6, 9]])
        cell_method = CellMethod(
            "difference", coords=["projection_y_coordinate"],
            intervals='1 grid length')
        result = self.plugin.create_difference_cube(
            self.cube, "projection_y_coordinate", diff_array)
        self.assertEqual(
            result.cell_methods[0], cell_method)
        self.assertEqual(
            result.attributes["form_of_difference"],
            "forward_difference")
        self.assertEqual(result.name(), 'difference_of_wind_speed')

    def test_othercoords(self):
        """Test that other coords are transferred properly"""
        diff_array = np.array([[1, 2, 3],
                               [3, 6, 9]])
        time_coord = self.cube.coord('time')
        proj_x_coord = self.cube.coord(axis='x')
        result = self.plugin.create_difference_cube(
            self.cube, "projection_y_coordinate", diff_array)
        self.assertEqual(result.coord(axis='x'), proj_x_coord)
        self.assertEqual(result.coord('time'), time_coord)
 def test_gradient(self):
     """Test that the correct metadata is set if the desired output is a
     gradient not a difference (except name)"""
     plugin = DifferenceBetweenAdjacentGridSquares(gradient=True)
     diff_array = np.array([[1, 2, 3],
                            [3, 6, 9]])
     result = plugin.create_difference_cube(
         self.cube, "projection_y_coordinate", diff_array)
     self.assertNotIn("form_of_difference", result.attributes)
     self.assertFalse(result.cell_methods)
 def setUp(self):
     """Set up cube."""
     data = np.array([[1, 2, 3], [2, 4, 6], [5, 10, 15]])
     self.diff_in_y_array = np.array([[1, 2, 3], [3, 6, 9]])
     self.cube = set_up_variable_cube(
         data,
         "wind_speed",
         "m s-1",
         "equalarea",
     )
     self.plugin = DifferenceBetweenAdjacentGridSquares()
 def setUp(self):
     """Set up cube."""
     data = np.array([[1, 2, 3],
                      [2, 4, 2],
                      [5, 10, 15]])
     x_coord = DimCoord(2.*np.arange(3), "projection_x_coordinate")
     y_coord = DimCoord(2.*np.arange(3), "projection_y_coordinate")
     self.cube = iris.cube.Cube(data, "wind_speed", units="m s-1",
                                dim_coords_and_dims=[(y_coord, 0),
                                                     (x_coord, 1)])
     self.plugin = DifferenceBetweenAdjacentGridSquares(gradient=True)
예제 #9
0
    def absolute_differences_between_adjacent_grid_squares(cube, threshold):
        """
        Compute the absolute differences between grid squares and put the
        resulting cubes into a cubelist.

        Args:
            cube : Iris.cube.Cube
                The cube from which adjacent grid square differences will be
                calculated.
            threshold : float
                The threshold that will be applied.

        Returns:
            cubelist : Iris.cube.CubeList
                Cubelist containing cubes with the absolute difference
                between adjacent grid squares along x and y, respectively.
        """
        diff_along_x_cube, diff_along_y_cube = (
            DifferenceBetweenAdjacentGridSquares().process(cube))
        # Compute the absolute values of the differences to ensure that
        # negative differences are included.
        diff_along_x_cube.data = np.absolute(diff_along_x_cube.data)
        diff_along_y_cube.data = np.absolute(diff_along_y_cube.data)
        cubelist = iris.cube.CubeList([diff_along_x_cube, diff_along_y_cube])
        return cubelist
예제 #10
0
 def setUp(self):
     """Set up cube & plugin"""
     self.plugin = OrographicAlphas(min_alpha=0.3, max_alpha=0.5)
     self.cube = set_up_cube()
     self.gradient_x, self.gradient_y = \
         DifferenceBetweenAdjacentGridSquares(gradient=True).process(
             self.cube)
예제 #11
0
 def setUp(self):
     """Set up cube & plugin"""
     self.plugin = OrographicSmoothingCoefficients(
         min_smoothing_coefficient=0.5, max_smoothing_coefficient=0.3)
     self.cube = set_up_cube()
     self.gradient_x, self.gradient_y = DifferenceBetweenAdjacentGridSquares(
         gradient=True).process(self.cube)
class Test_create_difference_cube(IrisTest):
    """Test the create_difference_cube method."""
    def setUp(self):
        """Set up cube."""
        data = np.array([[1, 2, 3], [2, 4, 6], [5, 10, 15]])
        self.diff_in_y_array = np.array([[1, 2, 3], [3, 6, 9]])
        self.cube = set_up_variable_cube(
            data,
            "wind_speed",
            "m s-1",
            "equalarea",
        )
        self.plugin = DifferenceBetweenAdjacentGridSquares()

    def test_y_dimension(self):
        """Test differences calculated along the y dimension."""
        points = self.cube.coord(axis="y").points
        expected_y = (points[1:] + points[:-1]) / 2
        result = self.plugin.create_difference_cube(self.cube,
                                                    "projection_y_coordinate",
                                                    self.diff_in_y_array)
        self.assertIsInstance(result, Cube)
        self.assertArrayAlmostEqual(result.coord(axis="y").points, expected_y)
        self.assertArrayEqual(result.data, self.diff_in_y_array)

    def test_x_dimension(self):
        """Test differences calculated along the x dimension."""
        diff_array = np.array([[1, 1], [2, 2], [5, 5]])
        points = self.cube.coord(axis="x").points
        expected_x = (points[1:] + points[:-1]) / 2
        result = self.plugin.create_difference_cube(self.cube,
                                                    "projection_x_coordinate",
                                                    diff_array)
        self.assertIsInstance(result, Cube)
        self.assertArrayAlmostEqual(result.coord(axis="x").points, expected_x)
        self.assertArrayEqual(result.data, diff_array)

    def test_othercoords(self):
        """Test that other coords are transferred properly"""
        time_coord = self.cube.coord("time")
        proj_x_coord = self.cube.coord(axis="x")
        result = self.plugin.create_difference_cube(self.cube,
                                                    "projection_y_coordinate",
                                                    self.diff_in_y_array)
        self.assertEqual(result.coord(axis="x"), proj_x_coord)
        self.assertEqual(result.coord("time"), time_coord)
예제 #13
0
 def test_basic(self):
     """Test data are as expected"""
     expected = np.array([[1.53125, 2.53125, 3.78125], [0., 0.5, 2.],
                          [1.53125, 0.03125, 0.78125]])
     gradient_x, _ = \
         DifferenceBetweenAdjacentGridSquares(gradient=True).process(
             self.cube)
     alpha_x = self.plugin.unnormalised_alphas(gradient_x)
     self.assertArrayAlmostEqual(alpha_x.data, expected)
예제 #14
0
    def _orography_gradients(self):
        """
        Calculates the dimensionless gradient of self.topography along both
        spatial axes, smoothed along the perpendicular axis.  If spatial
        coordinates are not in the same units as topography height (m),
        converts coordinate units in place.

        Returns:
            (tuple): tuple containing:
                **gradx** (iris.cube.Cube):
                    2D cube of dimensionless topography gradients in the
                    positive x direction
                **grady** (iris.cube.Cube):
                    2D cube of dimensionless topography gradients in the
                    positive y direction
        """
        self.topography.coord(axis='x').convert_units(self.topography.units)
        xdim = self.topography.coord_dims(self.topography.coord(axis='x'))[0]
        self.topography.coord(axis='y').convert_units(self.topography.units)
        ydim = self.topography.coord_dims(self.topography.coord(axis='y'))[0]

        # smooth topography by +/- one grid cell along the perpendicular axis
        # before calculating each gradient (as done in STEPS)
        topo_smx = uniform_filter1d(self.topography.data, 3, axis=ydim)
        topo_smx_cube = self.topography.copy(data=topo_smx)
        gradx, _ = DifferenceBetweenAdjacentGridSquares(
            gradient=True).process(topo_smx_cube)
        gradx.units = '1'

        topo_smy = uniform_filter1d(self.topography.data, 3, axis=xdim)
        topo_smy_cube = self.topography.copy(data=topo_smy)
        _, grady = DifferenceBetweenAdjacentGridSquares(
            gradient=True).process(topo_smy_cube)
        grady.units = '1'

        return gradx, grady
예제 #15
0
    def process(self, cube):
        """
        This creates the smoothing_coefficient cubes. It returns one for the x
        direction and one for the y direction. It uses the
        DifferenceBetweenAdjacentGridSquares plugin to calculate an average
        gradient across each grid square.  These gradients are then used to
        calculate "smoothing_coefficient" arrays that are normalised between a
        user-specified max and min.

        Args:
            cube (iris.cube.Cube):
                A 2D field of orography on the grid for which
                smoothing_coefficients are to be generated.
        Returns:
            (iris.cube.CubeList): containing:
                **smoothing_coefficient_x** (iris.cube.Cube): A cube of
                    orography-dependent smoothing_coefficients calculated in
                    the x direction.

                **smoothing_coefficient_y** (iris.cube.Cube): A cube of
                    orography-dependent smoothing_coefficients calculated in
                    the y direction.
        """
        if not isinstance(cube, iris.cube.Cube):
            raise ValueError("OrographicSmoothingCoefficients() expects cube "
                             "input, got {}".format(type(cube)))

        if len(cube.data.shape) != 2:
            raise ValueError(
                "Expected orography on 2D grid, got {} dims".format(
                    len(cube.data.shape)))

        gradient_x, gradient_y = DifferenceBetweenAdjacentGridSquares(
            gradient=True)(cube)
        (
            smoothing_coefficient_x,
            smoothing_coefficient_y,
        ) = self.gradient_to_smoothing_coefficient(gradient_x, gradient_y)

        return iris.cube.CubeList(
            [smoothing_coefficient_x, smoothing_coefficient_y])
예제 #16
0
    def process(self, cube):
        """
        This creates the alpha cubes. It returns one for the x direction and
        one for the y direction. It uses the
        DifferenceBetweenAdjacentGridSquares plugin to calculate an average
        gradient across each grid square.  These gradients are then used to
        calculate "alpha" smoothing arrays that are normalised between a
        user-specified max and min.

        Args:
            cube (iris.cube.Cube):
                A 2D cube of the orography for the grid we want to get alphas
                for.

        Returns:
            (tuple): tuple containing

                **alpha_x** (iris.cube.Cube) - A cube of orography-dependent
                    alphas calculated in the x direction.

                **alpha_y** (iris.cube.Cube) - A cube of orography-dependent
                    alphas calculated in the y direction.
        """
        if not isinstance(cube, iris.cube.Cube):
            raise ValueError(
                'OrographicAlphas() expects cube input, got {}'.format(
                    type(cube)))

        if len(cube.data.shape) != 2:
            raise ValueError(
                'Expected orography on 2D grid, got {} dims'.format(
                    len(cube.data.shape)))

        gradient_x, gradient_y = \
            DifferenceBetweenAdjacentGridSquares(gradient=True).process(cube)
        alpha_x, alpha_y = self.gradient_to_alpha(gradient_x, gradient_y)

        return alpha_x, alpha_y
class Test_process(IrisTest):
    """Test the process method."""
    def setUp(self):
        """Set up cube."""
        data = np.array([[1, 2, 3], [2, 4, 6], [5, 10, 15]])
        self.cube = set_up_variable_cube(
            data,
            "wind_speed",
            "m s-1",
            "equalarea",
            realizations=np.array([1, 2]),
        )
        self.plugin = DifferenceBetweenAdjacentGridSquares()

    def test_basic(self):
        """Test that differences are calculated along both the x and
        y dimensions and returned as separate cubes."""
        expected_x = np.array([[1, 1], [2, 2], [5, 5]])
        expected_y = np.array([[1, 2, 3], [3, 6, 9]])
        result = self.plugin.process(self.cube)
        self.assertIsInstance(result[0], Cube)
        self.assertArrayEqual(result[0].data, expected_x)
        self.assertIsInstance(result[1], Cube)
        self.assertArrayEqual(result[1].data, expected_y)

    def test_metadata(self):
        """Test the resulting metadata is correct."""
        cell_method_x = CellMethod("difference",
                                   coords=["projection_x_coordinate"],
                                   intervals="1 grid length")
        cell_method_y = CellMethod("difference",
                                   coords=["projection_y_coordinate"],
                                   intervals="1 grid length")

        result = self.plugin.process(self.cube)
        for cube, cm in zip(result, [cell_method_x, cell_method_y]):
            self.assertEqual(cube.cell_methods[0], cm)
            self.assertEqual(cube.attributes["form_of_difference"],
                             "forward_difference")
            self.assertEqual(cube.name(), "difference_of_wind_speed")

    def test_3d_cube(self):
        """Test the differences are calculated along both the x and
        y dimensions and returned as separate cubes when a 3d cube is input."""
        data = np.array([[[1, 2, 3], [2, 4, 6], [5, 10, 15]],
                         [[1, 2, 3], [2, 2, 6], [5, 10, 20]]])
        expected_x = np.array([[[1, 1], [2, 2], [5, 5]],
                               [[1, 1], [0, 4], [5, 10]]])
        expected_y = np.array([[[1, 2, 3], [3, 6, 9]], [[1, 0, 3], [3, 8,
                                                                    14]]])
        cube = set_up_variable_cube(
            data,
            "wind_speed",
            "m s-1",
            "equalarea",
            realizations=np.array([1, 2]),
        )
        result = self.plugin.process(cube)
        self.assertIsInstance(result[0], iris.cube.Cube)
        self.assertArrayEqual(result[0].data, expected_x)
        self.assertIsInstance(result[1], iris.cube.Cube)
        self.assertArrayEqual(result[1].data, expected_y)