示例#1
0
    def _orography_gradients(self) -> Tuple[Cube, Cube]:
        """
        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:
            - 2D cube of dimensionless topography gradients in the
              positive x direction
            - 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, _ = GradientBetweenAdjacentGridSquares(
            regrid=True)(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 = GradientBetweenAdjacentGridSquares(
            regrid=True)(topo_smy_cube)
        grady.units = "1"

        return gradx, grady
 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 = GradientBetweenAdjacentGridSquares(
         regrid=True
     ).process(self.cube)
def test_gradient(wind_speed, make_expected, grid):
    """Check calculating the gradient with and without regridding"""
    expected_x = make_expected(grid["xshape"], 1)
    expected_y = make_expected(grid["yshape"], 2)
    gradient_x, gradient_y = GradientBetweenAdjacentGridSquares(regrid=grid["regrid"])(
        wind_speed
    )
    for result, expected in zip((gradient_x, gradient_y), (expected_x, expected_y)):
        assert result.name() == expected.name()
        assert result.attributes == expected.attributes
        assert result.units == expected.units
        np.testing.assert_allclose(result.data, expected.data, rtol=1e-5, atol=1e-8)
 def test_basic(self):
     """Test data are as expected"""
     expected = np.array(
         [[1.53125, 2.53125, 3.78125], [0.0, 0.5, 2.0], [1.53125, 0.03125, 0.78125]]
     )
     gradient_x, _ = GradientBetweenAdjacentGridSquares(regrid=True).process(
         self.cube
     )
     smoothing_coefficient_x = self.plugin.unnormalised_smoothing_coefficients(
         gradient_x
     )
     self.assertArrayAlmostEqual(smoothing_coefficient_x.data, expected)
示例#5
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 = GradientBetweenAdjacentGridSquares()(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])
    def process(self, cube: Cube, mask: Optional[Cube] = None) -> CubeList:
        """
        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:
                A 2D field of orography on the grid for which
                smoothing_coefficients are to be generated.
            mask:
                A mask that defines where the smoothing coefficients should
                be zeroed. The mask must have the same spatial dimensions as
                the orography cube. How the mask is used to zero smoothing
                coefficients is determined by the plugin configuration arguments.

        Returns:
            - A cube of orography-dependent smoothing_coefficients calculated in
              the x direction.
            - 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)
                )
            )
        if mask is not None and (
            mask.coords(dim_coords=True) != cube.coords(dim_coords=True)
        ):
            raise ValueError(
                "If a mask is provided it must have the same grid as the "
                "orography field."
            )

        # Enforce coordinate order for simpler processing.
        original_order = [crd.name() for crd in cube.coords(dim_coords=True)]
        target_order = [cube.coord(axis="y").name(), cube.coord(axis="x").name()]
        enforce_coordinate_ordering(cube, target_order)

        # Returns two cubes, ordered gradient in x and gradient in y.
        gradients = GradientBetweenAdjacentGridSquares()(cube)

        # Calculate unscaled smoothing coefficients.
        smoothing_coefficients = iris.cube.CubeList()
        iterator = zip(
            gradients, ["smoothing_coefficient_x", "smoothing_coefficient_y"]
        )
        for gradient, name in iterator:
            coefficient_data = self.unnormalised_smoothing_coefficients(gradient)
            smoothing_coefficients.append(
                self.create_coefficient_cube(
                    coefficient_data, gradient, name, cube.attributes.copy()
                )
            )

        # Scale the smoothing coefficients between provided values.
        smoothing_coefficients = self.scale_smoothing_coefficients(
            smoothing_coefficients
        )

        # If a mask has been provided, zero coefficients where required.
        if mask is not None:
            enforce_coordinate_ordering(mask, target_order)
            self.zero_masked(*smoothing_coefficients, mask)

        for smoothing_coefficient in smoothing_coefficients:
            enforce_coordinate_ordering(smoothing_coefficient, original_order)

        return smoothing_coefficients