def test_wind_speed_data_check(self): """ Test that the plugin returns an iris.cube.CubeList of wind_speed cubes with the expected data, where the plugin returns a cubelist of, firstly, the predictor and, secondly the variance. The ensemble mean is the predictor. """ predictor_data = np.array([[2.9999862, 10.49998827, 17.99999034], [25.4999924, 32.99999447, 40.49999654], [47.99999861, 55.50000068, 63.00000275]]) variance_data = np.array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) calibration_method = "ensemble model output_statistics" distribution = "truncated gaussian" desired_units = "m s^-1" plugin = Plugin(calibration_method, distribution, desired_units) result = plugin.process(self.current_wind_speed_forecast_cube, self.historic_wind_speed_forecast_cube, self.wind_speed_truth_cube) self.assertArrayAlmostEqual(result[0][0].data, predictor_data) self.assertArrayAlmostEqual(result[1][0].data, variance_data)
def test_basic(self): """Ensure that the optimised_coeffs are returned as a dictionary, and the coefficient names are returned as a list.""" current_forecast = self.current_temperature_forecast_cube historic_forecasts = self.historic_temperature_forecast_cube truth = self.temperature_truth_cube distribution = "gaussian" desired_units = "degreesC" plugin = Plugin(distribution, desired_units) result = plugin.estimate_coefficients_for_ngr(current_forecast, historic_forecasts, truth) optimised_coeffs, coeff_names = result self.assertIsInstance(optimised_coeffs, dict) self.assertIsInstance(coeff_names, list) for key in optimised_coeffs.keys(): self.assertEqual(len(optimised_coeffs[key]), len(coeff_names))
def test_basic_mean_predictor(self): """ Test that the plugin returns a list containing the initial guess for the calibration coefficients, when the ensemble mean is used as the predictor. """ cube = self.cube current_forecast_predictor = cube.collapsed("realization", iris.analysis.MEAN) truth = cube.collapsed("realization", iris.analysis.MAX) distribution = "gaussian" desired_units = "degreesC" predictor_of_mean_flag = "mean" estimate_coefficients_from_linear_model_flag = False plugin = Plugin(distribution, desired_units) result = plugin.compute_initial_guess( truth, current_forecast_predictor, predictor_of_mean_flag, estimate_coefficients_from_linear_model_flag) self.assertIsInstance(result, list)
def test_realizations_predictor_estimate_coefficients(self): """ Test that the plugin returns the expected values for the initial guess for the calibration coefficients, when the ensemble mean is used as the predictor. The coefficients are estimated using a linear model. In this case, the result of the linear regression is for an intercept of 0.333333 with different weights for the realizations because some of the realizations are closer to the truth, in this instance. """ data = [0., 1., 0.333333, 0., 0.333333, 0.666667] predictor_of_mean_flag = "realizations" estimate_coefficients_from_linear_model_flag = True plugin = Plugin(self.distribution, self.desired_units) result = plugin.compute_initial_guess( self.truth, self.current_forecast_predictor_realizations, predictor_of_mean_flag, estimate_coefficients_from_linear_model_flag, no_of_realizations=self.no_of_realizations) self.assertArrayAlmostEqual(result, data)
def test_realizations_predictor_max_iterations(self): """ Test that the plugin returns a list of coefficients equal to specific values, when the ensemble realizations are the predictor assuming a truncated normal distribution and the value specified for the max_iterations is overridden. The coefficients are calculated by minimising the CRPS and using a set default value for the initial guess. """ predictor_of_mean_flag = "realizations" max_iterations = 1000 distribution = "truncated_gaussian" plugin = Plugin(tolerance=self.tolerance, max_iterations=max_iterations) result = plugin.process(self.initial_guess_for_realization, self.forecast_predictor_realizations, self.truth, self.forecast_variance, predictor_of_mean_flag, distribution) self.assertEMOSCoefficientsAlmostEqual( result, self.expected_realizations_coefficients)
def test_calibrated_variance_realizations(self): """ Test that the plugin returns values for the calibrated forecasts, which match the expected values when the individual ensemble realizations are used as the predictor. """ data = np.array([[34.333333, 34.333333, 34.333333], [34.333333, 34.333333, 34.333333], [34.333333, 34.333333, 34.333333]]) cube = self.current_temperature_forecast_cube predictor_cube = cube.copy() variance_cube = cube.collapsed("realization", iris.analysis.VARIANCE) plugin = Plugin(cube, self.coeffs_from_realizations, predictor_of_mean_flag="realizations") _, forecast_variance = plugin._apply_params(predictor_cube, variance_cube) self.assertArrayAlmostEqual(forecast_variance.data, data, decimal=4)
def test_statsmodels_realizations(self, warning_list=None): """ Test that the plugin raises the desired warning if the statsmodels module is not found for when the predictor is the ensemble realizations. """ import imp try: statsmodels_found = imp.find_module('statsmodels') statsmodels_found = True except ImportError: statsmodels_found = False cube = self.cube historic_forecasts = CubeList([]) for index in [1.0, 2.0, 3.0, 4.0, 5.0]: temp_cube = cube.copy() temp_cube.coord("time").points = (temp_cube.coord("time").points - index) historic_forecasts.append(temp_cube) historic_forecasts.concatenate_cube() current_forecast_predictor = cube truth = cube.collapsed("realization", iris.analysis.MAX) distribution = "gaussian" desired_units = "degreesC" predictor_of_mean_flag = "realizations" no_of_realizations = 3 estimate_coefficients_from_linear_model_flag = True if not statsmodels_found: plugin = Plugin(distribution, desired_units, predictor_of_mean_flag=predictor_of_mean_flag) self.assertTrue(len(warning_list) == 1) self.assertTrue( any(item.category == ImportWarning for item in warning_list)) self.assertTrue( "The statsmodels can not be imported" in str(warning_list[0]))
def test_calibrated_predictor_realizations(self): """ Test that the plugin returns values for the calibrated forecasts, which match the expected values when the individual ensemble realizations are used as the predictor. """ data = np.array([[239.904142, 251.659267, 263.414393], [275.169518, 286.92465, 298.67975], [310.43488, 322.19, 333.94516]], dtype=np.float32) cube = self.current_temperature_forecast_cube cube1 = cube.copy() cube2 = cube.copy() cube2.coord("time").points = cube2.coord("time").points + 3 cube2.data += 3 cube = concatenate_cubes(CubeList([cube1, cube2])) optimised_coeffs = {} for time_slice in cube.slices_over("time"): the_date = datetime_from_timestamp(time_slice.coord("time").points) optimised_coeffs[the_date] = np.array( [5, 1, 0, 0.57, 0.6, 0.6], dtype=np.float32) self.coeff_names = ["gamma", "delta", "a", "beta"] predictor_cube = cube.copy() variance_cube = cube.collapsed("realization", iris.analysis.VARIANCE) predictor_of_mean_flag = "realizations" plugin = Plugin(self.cube, optimised_coeffs, self.coeff_names) forecast_predictor, _, _ = plugin._apply_params( predictor_cube, variance_cube, optimised_coeffs, self.coeff_names, predictor_of_mean_flag) self.assertArrayAlmostEqual(forecast_predictor[0].data, data, decimal=4)
def test_coefficient_values_truncated_gaussian_distribution_realization( self): """Ensure that the values for the optimised_coefficients match the expected values, and the coefficient names also match expected values for a truncated Gaussian distribution where the realizations are used as the predictor of the mean.""" import imp try: imp.find_module('statsmodels') statsmodels_found = True except ImportError: statsmodels_found = False if statsmodels_found: data = [ 0.11821805, -0.00474737, 0.17631301, 0.17178835, 0.66749225, 0.72287342 ] else: data = [ 2.05550997, 0.10577237, 0.00028531, 0.53208837, 0.67233013, 0.53704241 ] distribution = "truncated gaussian" current_cycle = "20171110T0000Z" predictor_of_mean_flag = "realizations" expected_coeff_names = ([ 'gamma', 'delta', 'alpha', 'beta0', 'beta1', 'beta2' ]) plugin = Plugin(distribution, current_cycle, predictor_of_mean_flag=predictor_of_mean_flag) result = plugin.estimate_coefficients_for_ngr( self.historic_wind_speed_forecast_cube, self.wind_speed_truth_cube) self.assertArrayAlmostEqual(result.data, data) self.assertArrayEqual( result.coord("coefficient_name").points, expected_coeff_names)
def test_coefficient_values_for_gaussian_distribution(self): """Ensure that the values for the optimised_coefficients match the expected values, and the coefficient names also match expected values for a Gaussian distribution.""" data = [ 4.55819380e-06, -8.02401974e-09, 1.66667055e+00, 1.00000011e+00 ] distribution = "gaussian" current_cycle = "20171110T0000Z" desired_units = "Celsius" plugin = Plugin(distribution, current_cycle, desired_units=desired_units) result = plugin.estimate_coefficients_for_ngr( self.historic_temperature_forecast_cube, self.temperature_truth_cube) self.assertArrayAlmostEqual(result.data, data) self.assertArrayEqual( result.coord("coefficient_name").points, self.coeff_names)
def test_mean_predictor_estimate_coefficients(self): """ Test that the plugin returns the expected values for the initial guess for the calibration coefficients, when the ensemble mean is used as the predictor. The coefficients are estimated using a linear model. """ data = np.array([1, 1, 2.66663, 1], dtype=np.float32) current_forecast_predictor = self.cube.collapsed( "realization", iris.analysis.MEAN) truth = self.cube.collapsed("realization", iris.analysis.MAX) distribution = "gaussian" desired_units = "degreesC" predictor_of_mean_flag = "mean" estimate_coefficients_from_linear_model_flag = True plugin = Plugin(distribution, desired_units) result = plugin.compute_initial_guess( truth, current_forecast_predictor, predictor_of_mean_flag, estimate_coefficients_from_linear_model_flag) self.assertArrayAlmostEqual(result, data, decimal=5)
def test_basic_mean_predictor_value_check(self): """ Test that the plugin returns the expected values for the initial guess for the calibration coefficients, when the ensemble mean is used as the predictor. As coefficients are not estimated using a linear model, the default values for the initial guess are used. """ data = [1, 1, 0, 1] current_forecast_predictor = self.cube.collapsed( "realization", iris.analysis.MEAN) truth = self.cube.collapsed("realization", iris.analysis.MAX) distribution = "gaussian" desired_units = "degreesC" predictor_of_mean_flag = "mean" estimate_coefficients_from_linear_model_flag = False plugin = Plugin(distribution, desired_units) result = plugin.compute_initial_guess( truth, current_forecast_predictor, predictor_of_mean_flag, estimate_coefficients_from_linear_model_flag) self.assertArrayAlmostEqual(result, data)
def test_basic_realizations_predictor(self): """ Test that the plugin returns a list containing the initial guess for the calibration coefficients, when the individual ensemble realizations are used as predictors. """ current_forecast_predictor = self.cube.copy() truth = self.cube.collapsed("realization", iris.analysis.MAX) distribution = "gaussian" desired_units = "degreesC" predictor_of_mean_flag = "realizations" no_of_realizations = 3 estimate_coefficients_from_linear_model_flag = False plugin = Plugin(distribution, desired_units) result = plugin.compute_initial_guess( truth, current_forecast_predictor, predictor_of_mean_flag, estimate_coefficients_from_linear_model_flag, no_of_realizations=no_of_realizations) self.assertIsInstance(result, np.ndarray)
def test_truth_unit_conversion(self): """Ensure the expected optimised coefficients are generated, even if the input truth cube has different units.""" data = [ 4.55819380e-06, -8.02401974e-09, 1.66667055e+00, 1.00000011e+00 ] truth = self.temperature_truth_cube truth.convert_units("Fahrenheit") distribution = "gaussian" current_cycle = "20171110T0000Z" desired_units = "degreesC" plugin = Plugin(distribution, current_cycle, desired_units=desired_units) result = plugin.estimate_coefficients_for_ngr( self.historic_temperature_forecast_cube, truth) self.assertArrayAlmostEqual(result.data, data, decimal=5)
def test_basic_truncated_normal_realizations_predictor(self): """Test that the plugin returns a numpy array.""" initial_guess = [5, 1, 0, 1, 1, 1] initial_guess = np.array(initial_guess, dtype=np.float32) cube = set_up_temperature_cube() forecast_predictor = cube.copy() forecast_variance = cube.collapsed( "realization", iris.analysis.VARIANCE) truth = cube.collapsed("realization", iris.analysis.MAX) predictor_of_mean_flag = "realizations" plugin = Plugin() distribution = "truncated gaussian" result = plugin.crps_minimiser_wrapper( initial_guess, forecast_predictor, truth, forecast_variance, predictor_of_mean_flag, distribution) self.assertIsInstance(result, np.ndarray) self.assertArrayAlmostEqual( result, [6.24021609e+00, 1.35694934e+00, 1.84642787e-03, 5.55444682e-01, 5.04367388e-01, 6.68575194e-01])
def test_output_coefficients_realizations(self): """ Test that the plugin returns a tuple containing cubes with the expected coefficient names when using ensemble realizations as the predictor of the mean. """ cube = self.current_temperature_forecast_cube optimised_coeffs = {} the_date = datetime_from_timestamp(cube.coord("time").points) optimised_coeffs[the_date] = np.array([ 4.55819380e-06, -8.02401974e-09, 1.66667055e+00, 1.00000011e+00, 1.00000011e+00, 1.00000011e+00 ]) plugin = Plugin(cube, optimised_coeffs, self.coeff_names, predictor_of_mean_flag="realizations") _, _, coefficients = plugin.apply_params_entry() for result, coeff_name, coeff in zip(coefficients, self.coeff_names, optimised_coeffs[the_date]): self.assertEqual(result.long_name, coeff_name) self.assertArrayAlmostEqual(result.data, coeff)
def test_calibrated_variance_realizations(self): """ Test that the plugin returns values for the calibrated forecasts, which match the expected values when the individual ensemble realizations are used as the predictor. """ data = np.array([[34.333333, 34.333333, 34.333333], [34.333333, 34.333333, 34.333333], [34.333333, 34.333333, 34.333333]]) cube = self.current_temperature_forecast_cube cube1 = cube.copy() cube2 = cube.copy() cube2.coord("time").points = cube2.coord("time").points + 3 cube2.data += 3 cube = concatenate_cubes(CubeList([cube1, cube2])) optimised_coeffs = {} for time_slice in cube.slices_over("time"): the_date = datetime_from_timestamp(time_slice.coord("time").points) optimised_coeffs[the_date] = np.array( [5, 1, 0, 0.57, 0.6, 0.6]) self.coeff_names = ["gamma", "delta", "a", "beta"] predictor_cube = cube.copy() variance_cube = cube.collapsed("realization", iris.analysis.VARIANCE) predictor_of_mean_flag = "realizations" plugin = Plugin(self.cube, optimised_coeffs, self.coeff_names) _, forecast_variance, _ = plugin._apply_params( predictor_cube, variance_cube, optimised_coeffs, self.coeff_names, predictor_of_mean_flag) self.assertArrayAlmostEqual(forecast_variance[0].data, data, decimal=4)
def test_truth_data_is_fake_catch_warning(self, warning_list=None): """ Ensure that a ValueError with the expected text is generated, if the input data is None, rather than a cube. """ current_forecast = self.current_temperature_forecast_cube historic_forecasts = self.historic_temperature_forecast_cube truth = "fake" distribution = "gaussian" desired_units = "degreesC" plugin = Plugin(distribution, desired_units) plugin.estimate_coefficients_for_ngr(current_forecast, historic_forecasts, truth) self.assertTrue(len(warning_list) == 1) self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue("is not a Cube or CubeList" in str(warning_list[0]))
def test_calibrated_predictor_realizations(self): """ Test that the plugin returns values for the calibrated forecasts, which match the expected values when the individual ensemble realizations are used as the predictor. """ data = np.array([[239.904142, 251.659267, 263.414393], [275.169518, 286.92465, 298.67975], [310.43488, 322.19, 333.94516]], dtype=np.float32) cube = self.current_temperature_forecast_cube predictor_cube = cube.copy() variance_cube = cube.collapsed("realization", iris.analysis.VARIANCE) plugin = Plugin(cube, self.coeffs_from_realizations, predictor_of_mean_flag="realizations") forecast_predictor, _ = plugin._apply_params(predictor_cube, variance_cube) self.assertArrayAlmostEqual(forecast_predictor.data, data, decimal=4)
def test_coefficient_values_for_gaussian_distribution_realizations(self): """Ensure that the values for the optimised_coefficients match the expected values, and the coefficient names also match expected values for a Gaussian distribution where the realizations are used as the predictor of the mean.""" import imp try: imp.find_module('statsmodels') statsmodels_found = True except ImportError: statsmodels_found = False if statsmodels_found: data = [-0.00114, -0.00006, 1.00037, -0.00196, 0.99999, -0.00315] else: data = [ 4.30804737e-02, 1.39042785e+00, 8.99047025e-04, 2.02661310e-01, 9.27197381e-01, 3.17407626e-01 ] distribution = "gaussian" current_cycle = "20171110T0000Z" desired_units = "Celsius" predictor_of_mean_flag = "realizations" expected_coeff_names = ([ 'gamma', 'delta', 'alpha', 'beta0', 'beta1', 'beta2' ]) plugin = Plugin(distribution, current_cycle, desired_units=desired_units, predictor_of_mean_flag=predictor_of_mean_flag) result = plugin.estimate_coefficients_for_ngr( self.historic_temperature_forecast_cube, self.temperature_truth_cube) self.assertArrayAlmostEqual(result.data, data, decimal=5) self.assertArrayEqual( result.coord("coefficient_name").points, expected_coeff_names)
def test_wind_speed_data_check(self): """ Test that the plugin returns an iris.cube.CubeList of wind_speed cubes with the expected data, where the plugin returns a cubelist of, firstly, the predictor and, secondly the variance. The ensemble mean is the predictor. """ predictor_data = np.array( [[2.9999862, 10.499988, 17.999989], [25.49999, 32.999992, 40.499992], [47.999996, 55.499996, 63.]], dtype=np.float32) variance_data = np.array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]], dtype=np.float32) calibration_method = "ensemble model output_statistics" distribution = "truncated gaussian" desired_units = "m s^-1" plugin = Plugin(calibration_method, distribution, desired_units) calibrated_predictor, calibrated_variance = plugin.process( self.current_wind_speed_forecast_cube, self.historic_wind_speed_forecast_cube, self.wind_speed_truth_cube) self.assertArrayAlmostEqual(calibrated_predictor.data, predictor_data) self.assertArrayAlmostEqual(calibrated_variance.data, variance_data)
def test_mean_predictor_estimate_coefficients_nans(self): """ Test that the plugin returns the expected values for the initial guess for the calibration coefficients, when the ensemble mean is used as the predictor, when one value from the input data is set to NaN. The coefficients are estimated using a linear model, where there is an offset of one between the truth and the forecast during the training period. Therefore, in this case the result of the linear regression is a gradient of 1 and an intercept of 1. """ data = np.array([0., 1., 1., 1.], dtype=np.float32) estimate_coefficients_from_linear_model_flag = True self.current_forecast_predictor_mean.data = ( self.current_forecast_predictor_mean.data.filled()) self.current_forecast_predictor_mean.data[0][0] = np.nan plugin = Plugin(self.distribution, self.desired_units) result = plugin.compute_initial_guess( self.truth, self.current_forecast_predictor_mean, self.predictor_of_mean_flag, estimate_coefficients_from_linear_model_flag) self.assertArrayAlmostEqual(result, data)
def test_calibrated_variance_statsmodels_realizations(self): """ Test that the plugin returns the expected values for the calibrated ensemble variance when the ensemble realizations are used as the predictor. The input coefficients have been generated using statsmodels. Check that the calibrated variance is similar to when the ensemble mean is used as the predictor. """ cube = self.current_temperature_forecast_cube predictor_cube = cube.copy() variance_cube = cube.collapsed("realization", iris.analysis.VARIANCE) plugin = Plugin(cube, self.coeffs_from_statsmodels_realizations, predictor_of_mean_flag="realizations") _, forecast_variance = plugin._apply_params( predictor_cube, variance_cube) self.assertCalibratedVariablesAlmostEqual( forecast_variance.data, self.expected_calibrated_variance_statsmodels_realizations) self.assertArrayAlmostEqual( forecast_variance.data, self.expected_calibrated_variance_mean, decimal=0)
def test_truth_data_length_zero_catch_warning(self, warning_list=None): """ Ensure that a ValueError with the expected text is generated, if the input data is None, rather than a cube. """ current_forecast = self.current_temperature_forecast_cube historic_forecasts = self.historic_temperature_forecast_cube truth = iris.cube.CubeList([]) distribution = "gaussian" desired_units = "degreesC" plugin = Plugin(distribution, desired_units) plugin.estimate_coefficients_for_ngr(current_forecast, historic_forecasts, truth) warning_msg = ("Insufficient input data present to estimate " "coefficients using NGR.") self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue(any(warning_msg in str(item) for item in warning_list))
def test_truth_data_has_wrong_time_catch_warning(self, warning_list=None): """ Ensure that a ValueError with the expected text is generated, if the input data is None, rather than a cube. """ current_forecast = self.current_temperature_forecast_cube historic_forecasts = self.historic_temperature_forecast_cube truth = self.temperature_truth_cube truth.coord("forecast_reference_time").points += 10 distribution = "gaussian" desired_units = "degreesC" plugin = Plugin(distribution, desired_units) plugin.estimate_coefficients_for_ngr(current_forecast, historic_forecasts, truth) warning_msg = "Unable to calibrate for the time points" self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue(any(warning_msg in str(item) for item in warning_list))
def test_statsmodels_mean(self): """ Test that the plugin raises no warnings if the statsmodels module is not found for when the predictor is the ensemble mean. """ warnings.simplefilter("always") import imp try: statsmodels_found = imp.find_module('statsmodels') statsmodels_found = True except ImportError: statsmodels_found = False cube = self.cube historic_forecasts = CubeList([]) for index in [1.0, 2.0, 3.0, 4.0, 5.0]: temp_cube = cube.copy() temp_cube.coord("time").points = (temp_cube.coord("time").points - index) historic_forecasts.append(temp_cube) historic_forecasts.concatenate_cube() current_forecast_predictor = cube truth = cube.collapsed("realization", iris.analysis.MAX) distribution = "gaussian" desired_units = "degreesC" predictor_of_mean_flag = "mean" no_of_members = 3 estimate_coefficients_from_linear_model_flag = True if not statsmodels_found: with warnings.catch_warnings(record=True) as warning_list: plugin = Plugin(distribution, desired_units, predictor_of_mean_flag=predictor_of_mean_flag) self.assertTrue(len(warning_list) == 0)
def test_members_predictor_estimate_coefficients(self): """ Test that the plugin returns the expected values for the initial guess for the calibration coefficients, when the ensemble mean is used as the predictor. The coefficients are estimated using a linear model. """ warnings.simplefilter("always") import imp try: statsmodels_found = imp.find_module('statsmodels') statsmodels_found = True except ImportError: statsmodels_found = False if statsmodels_found: data = [1., 1., 0.13559322, -0.11864407, 0.42372881, 0.69491525] else: data = [1, 1, 0, 1, 1, 1] cube = self.cube current_forecast_predictor = cube truth = cube.collapsed("realization", iris.analysis.MAX) distribution = "gaussian" desired_units = "degreesC" predictor_of_mean_flag = "members" no_of_members = 3 estimate_coefficients_from_linear_model_flag = True plugin = Plugin(distribution, desired_units) result = plugin.compute_initial_guess( truth, current_forecast_predictor, predictor_of_mean_flag, estimate_coefficients_from_linear_model_flag, no_of_members=no_of_members) self.assertArrayAlmostEqual(result, data)
def test_normal_catch_warnings_percentage_change(self): """ Test that two warnings are generated if the minimisation does not result in a convergence. The first warning reports a that the minimisation did not result in convergence, whilst the second warning reports that the percentage change in the final iteration was greater than the tolerated value. The ensemble mean is the predictor. """ warnings.simplefilter("always") initial_guess = [500, 100, 0, 100] initial_guess = np.array(initial_guess, dtype=np.float32) cube = set_up_temperature_cube() forecast_predictor = cube.collapsed("realization", iris.analysis.MEAN) forecast_variance = cube.collapsed("realization", iris.analysis.VARIANCE) truth = cube.collapsed("realization", iris.analysis.MAX) predictor_of_mean_flag = "mean" plugin = Plugin() distribution = "gaussian" with warnings.catch_warnings(record=True) as warning_list: warnings.simplefilter("always") result = plugin.crps_minimiser_wrapper(initial_guess, forecast_predictor, truth, forecast_variance, predictor_of_mean_flag, distribution) self.assertTrue(len(warning_list) == 2) self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue("Minimisation did not result in convergence after" in str(warning_list[0])) self.assertTrue("The final iteration resulted in a percentage " "change" in str(warning_list[1]))
def test_calibrated_variance(self): """ Test that the plugin returns values for the calibrated variance, which match the expected values. """ data = np.array([[2.07777316e-11, 2.07777316e-11, 2.07777316e-11], [2.07777316e-11, 2.07777316e-11, 2.07777316e-11], [2.07777316e-11, 2.07777316e-11, 2.07777316e-11]]) cube = self.current_temperature_forecast_cube cube1 = cube.copy() cube2 = cube.copy() cube2.coord("time").points = cube2.coord("time").points + 3 cube2.data += 3 cube = concatenate_cubes(CubeList([cube1, cube2])) optimised_coeffs = {} for time_slice in cube.slices_over("time"): the_date = datetime_from_timestamp(time_slice.coord("time").points) optimised_coeffs[the_date] = self.default_optimised_coeffs predictor_cube = cube.collapsed("realization", iris.analysis.MEAN) variance_cube = cube.collapsed("realization", iris.analysis.VARIANCE) predictor_of_mean_flag = "mean" plugin = Plugin(self.cube, optimised_coeffs, self.coeff_names) _, forecast_variance, _ = plugin._apply_params(predictor_cube, variance_cube, optimised_coeffs, self.coeff_names, predictor_of_mean_flag) self.assertArrayAlmostEqual(forecast_variance[0].data, data)
def test_basic_truncated_normal_mean_predictor(self): """ Test that the plugin returns a numpy float value. The ensemble mean is the predictor. """ initial_guess = [5, 1, 0, 1] initial_guess = np.array(initial_guess, dtype=np.float32) cube = set_up_temperature_cube() forecast_predictor = cube.collapsed("realization", iris.analysis.MEAN) forecast_variance = cube.collapsed( "realization", iris.analysis.VARIANCE) truth = cube.collapsed("realization", iris.analysis.MAX) predictor_of_mean_flag = "mean" plugin = Plugin() distribution = "truncated gaussian" result = plugin.crps_minimiser_wrapper( initial_guess, forecast_predictor, truth, forecast_variance, predictor_of_mean_flag, distribution) self.assertIsInstance(result, np.ndarray) self.assertArrayAlmostEqual( result, [-0.08169791, -0.09784413, 0.00822535, 1.00956199])