def process(self, cubes, coordinates=None):
        """
        Aggregate the input reliability calibration table cubes and return the
        result.

        Args:
            cubes (list or iris.cube.CubeList):
                The cube or cubes containing the reliability calibration tables
                to aggregate.
            coordinates (list or None):
                A list of coordinates over which to aggregate the reliability
                calibration table using summation. If the argument is None and
                a single cube is provided, this cube will be returned
                unchanged.
        """
        coordinates = [] if coordinates is None else coordinates

        try:
            (cube, ) = cubes
        except ValueError:
            cubes = iris.cube.CubeList(cubes)
            self._check_frt_coord(cubes)
            cube = cubes.merge_cube()
            coordinates.append("forecast_reference_time")
        else:
            if not coordinates:
                return cube

        result = collapsed(cube, coordinates, iris.analysis.SUM)
        frt = create_unified_frt_coord(cube.coord("forecast_reference_time"))
        result.replace_coord(frt)
        return result
Exemple #2
0
    def test_coordinate_input_with_bounds(self):
        """Test the forecast reference time coordinate has the expected point,
        bounds, and type for an input multiple forecast reference times, each
        with bounds."""

        frt = "forecast_reference_time"
        cube = iris.cube.CubeList(
            [self.reliability_cube, self.different_frt]
        ).merge_cube()
        frt_coord = cube.coord(frt)

        expected_points = self.different_frt.coord(frt).points[0]
        expected_bounds = [
            [
                self.reliability_cube.coord(frt).bounds[0][0],
                self.different_frt.coord(frt).bounds[0][-1],
            ]
        ]
        result = create_unified_frt_coord(frt_coord)

        self.assertIsInstance(result, iris.coords.DimCoord)
        assert_array_equal(result.points, expected_points)
        assert_array_equal(result.bounds, expected_bounds)
        self.assertEqual(result.name(), frt_coord.name())
        self.assertEqual(result.units, frt_coord.units)
Exemple #3
0
    def test_coordinate_single_frt_input(self):
        """Test the forecast reference time coordinate has the expected point,
        bounds, and type for an input with a single forecast reference time
        point."""

        frt = "forecast_reference_time"
        frt_coord = self.forecast_1.coord(frt)

        expected_points = self.forecast_1.coord(frt).points[0]
        expected_bounds = [[self.forecast_1.coord(frt).points[0], expected_points]]
        result = create_unified_frt_coord(frt_coord)

        self.assertIsInstance(result, iris.coords.DimCoord)
        assert_array_equal(result.points, expected_points)
        assert_array_equal(result.bounds, expected_bounds)
        self.assertEqual(result.name(), frt_coord.name())
        self.assertEqual(result.units, frt_coord.units)
Exemple #4
0
def test_create_unified_frt_single_frt_input(forecast_grid):
    """Test the forecast reference time coordinate has the expected point,
    bounds, and type for an input with a single forecast reference time
    point."""

    frt = "forecast_reference_time"
    forecast_1 = forecast_grid[0, ...]
    frt_coord = forecast_1.coord(frt)

    expected_points = forecast_1.coord(frt).points[0]
    expected_bounds = [[forecast_1.coord(frt).points[0], expected_points]]
    result = create_unified_frt_coord(frt_coord)

    assert isinstance(result, iris.coords.DimCoord)
    assert_array_equal(result.points, expected_points)
    assert_array_equal(result.bounds, expected_bounds)
    assert result.name() == frt_coord.name()
    assert result.units == frt_coord.units
    def _create_reliability_table_cube(self, forecast, threshold_coord):
        """
        Construct a reliability table cube and populate it with the provided
        data. The returned cube will include a cycle hour coordinate, which
        describes the model cycle hour at which the forecast data was produced.
        It will further include the forecast period, threshold coordinate,
        and spatial coordinates from the forecast cube.

        Args:
            forecast (iris.cube.Cube):
                A cube slice across the spatial dimensions of the forecast
                data. This slice provides the time and threshold values that
                relate to the reliability_table_data.
            threshold_coord (iris.coords.DimCoord):
                The threshold coordinate.
        Returns:
            iris.cube.Cube:
                A reliability table cube.
        """
        def _get_coords_and_dims(coord_names):
            """Obtain the requested coordinates and their dimension index from
            the forecast slice cube."""
            coords_and_dims = []
            leading_coords = [probability_bins_coord, reliability_index_coord]
            for coord_name in coord_names:
                crd = forecast_slice.coord(coord_name)
                crd_dim = forecast_slice.coord_dims(crd)
                crd_dim = crd_dim[0] + len(leading_coords) if crd_dim else ()
                coords_and_dims.append((crd, crd_dim))
            return coords_and_dims

        forecast_slice = next(forecast.slices_over(["time", threshold_coord]))
        expected_shape = self.expected_table_shape + forecast_slice.shape
        dummy_data = np.zeros((expected_shape))

        diagnostic = find_threshold_coordinate(forecast).name()
        attributes = self._define_metadata(forecast)

        # Define reliability table specific coordinates
        probability_bins_coord = self._create_probability_bins_coord()
        (
            reliability_index_coord,
            reliability_name_coord,
        ) = self._create_reliability_table_coords()
        frt_coord = create_unified_frt_coord(
            forecast.coord("forecast_reference_time"))

        # List of required non-spatial coordinates from the forecast
        non_spatial_coords = ["forecast_period", diagnostic]

        # Construct a list of coordinates in the desired order
        dim_coords = [forecast.coord(axis=dim).name() for dim in ["x", "y"]]
        dim_coords_and_dims = _get_coords_and_dims(dim_coords)
        aux_coords_and_dims = _get_coords_and_dims(non_spatial_coords)
        dim_coords_and_dims.append((reliability_index_coord, 0))
        aux_coords_and_dims.append((reliability_name_coord, 0))
        dim_coords_and_dims.append((probability_bins_coord, 1))

        reliability_cube = iris.cube.Cube(
            dummy_data,
            units=1,
            attributes=attributes,
            dim_coords_and_dims=dim_coords_and_dims,
            aux_coords_and_dims=aux_coords_and_dims,
        )
        reliability_cube.add_aux_coord(frt_coord)
        reliability_cube.rename("reliability_calibration_table")

        return reliability_cube