Пример #1
0
def process(
    forecast: cli.inputcube,
    reliability_table: cli.inputcubelist = None,
):
    """
    Calibrate a probability forecast using the provided reliability calibration
    table. This calibration is designed to improve the reliability of
    probability forecasts without significantly degrading their resolution. If
    a reliability table is not provided, the input forecast is returned
    unchanged.

    The method implemented here is described in Flowerdew J. 2014. Calibrating
    ensemble reliability whilst preserving spatial structure. Tellus, Ser. A
    Dyn. Meteorol. Oceanogr. 66.

    Args:
        forecast (iris.cube.Cube):
            The forecast to be calibrated.
        reliability_table (iris.cube.Cube or iris.cube.CubeList):
            The reliability calibration table to use in calibrating the
            forecast. If input is a CubeList the CubeList should contain
            separate cubes for each threshold in the forecast cube.

    Returns:
        iris.cube.Cube:
            Calibrated forecast.
    """
    from improver.calibration.reliability_calibration import ApplyReliabilityCalibration

    if reliability_table is None:
        return forecast
    plugin = ApplyReliabilityCalibration()
    return plugin(forecast, reliability_table)
Пример #2
0
    def setUp(self):

        """Set up data for testing the interpolate method."""

        self.reliability_probabilities = np.array([0.0, 0.4, 0.8])
        self.observation_frequencies = np.array([0.2, 0.6, 1.0])
        self.plugin = Plugin()
Пример #3
0
    def test_values(self):
        """Test expected values are returned when two or more bins are
        available for interpolation."""

        expected_0 = (
            np.array([0.0, 0.25, 0.5, 0.75, 1.0]),
            np.array([0.0, 0.0, 0.25, 0.5, 0.75]),
        )
        expected_1 = (
            np.array([0.0, 0.25, 0.5, 0.75, 1.0]),
            np.array([0.25, 0.5, 0.75, 1.0, 1.0]),
        )
        plugin = Plugin()
        threshold_0 = plugin._calculate_reliability_probabilities(
            self.reliability_cube[0])
        threshold_1 = plugin._calculate_reliability_probabilities(
            self.reliability_cube[1])

        assert_array_equal(threshold_0, expected_0)
        assert_array_equal(threshold_1, expected_1)
Пример #4
0
def process(
    forecast: cli.inputcube,
    reliability_table: cli.inputcube = None,
    *,
    minimum_forecast_count=200,
):
    """
    Calibrate a probability forecast using the provided reliability calibration
    table. This calibration is designed to improve the reliability of
    probability forecasts without significantly degrading their resolution. If
    a reliability table is not provided, the input forecast is returned
    unchanged.

    The method implemented here is described in Flowerdew J. 2014. Calibrating
    ensemble reliability whilst preserving spatial structure. Tellus, Ser. A
    Dyn. Meteorol. Oceanogr. 66.

    Args:
        forecast (iris.cube.Cube):
            The forecast to be calibrated.
        reliability_table (iris.cube.Cube):
            The reliability calibration table to use in calibrating the
            forecast.
        minimum_forecast_count (int):
            The minimum number of forecast counts in a forecast probability
            bin for it to be used in calibration. If the reliability
            table for a forecast threshold includes any bins with
            insufficient counts that threshold will be returned unchanged.
            The default value of 200 is that used in Flowerdew 2014.
    Returns:
        iris.cube.Cube:
            Calibrated forecast.
    """
    from improver.calibration.reliability_calibration import ApplyReliabilityCalibration

    if reliability_table is None:
        return forecast

    plugin = ApplyReliabilityCalibration(
        minimum_forecast_count=minimum_forecast_count)
    return plugin(forecast, reliability_table)
Пример #5
0
class Test__interpolate(unittest.TestCase):
    """Test the _interpolate method."""
    def setUp(self):
        """Set up data for testing the interpolate method."""

        self.reliability_probabilities = np.array([0.0, 0.4, 0.8])
        self.observation_frequencies = np.array([0.2, 0.6, 1.0])
        self.plugin = Plugin()

    def test_unmasked_data(self):
        """Test unmasked data is interpolated and returned as expected."""

        expected = np.array([0.4, 0.6, 0.8])
        forecast_threshold = np.array([0.2, 0.4, 0.6])

        result = self.plugin._interpolate(
            forecast_threshold,
            self.reliability_probabilities,
            self.observation_frequencies,
        )

        assert_allclose(result, expected)

    def test_masked_data(self):
        """Test masked data is interpolated and returned with the original
        mask in place."""

        expected = np.ma.masked_array([np.nan, 0.6, 0.8], mask=[1, 0, 0])
        forecast_threshold = np.ma.masked_array([np.nan, 0.4, 0.6],
                                                mask=[1, 0, 0])

        result = self.plugin._interpolate(
            forecast_threshold,
            self.reliability_probabilities,
            self.observation_frequencies,
        )

        assert_allclose(result, expected)

    def test_clipping(self):
        """Test the result, when using data constructed to cause extrapolation
        to a probability outside the range 0 to 1, is clipped. In this case
        an input probability of 0.9 would  return a calibrated probability
        of 1.1 in the absence of clipping."""

        expected = np.array([0.4, 0.6, 1.0])
        forecast_threshold = np.array([0.2, 0.4, 0.9])

        result = self.plugin._interpolate(
            forecast_threshold,
            self.reliability_probabilities,
            self.observation_frequencies,
        )

        assert_allclose(result, expected)

    def test_reshaping(self):
        """Test that the result has the same shape as the forecast_threshold
        input data."""

        expected = np.array([[0.2, 0.325, 0.45], [0.575, 0.7, 0.825],
                             [0.95, 1.0, 1.0]])

        forecast_threshold = np.linspace(0, 1, 9).reshape((3, 3))

        result = self.plugin._interpolate(
            forecast_threshold,
            self.reliability_probabilities,
            self.observation_frequencies,
        )

        self.assertEqual(result.shape, expected.shape)
        assert_allclose(result, expected)