class Test__calculate_location_parameter_from_realizations( SetupCoefficientsCubes, EnsembleCalibrationAssertions ): """Test the _calculate_location_parameter_from_realizations method.""" @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def setUp(self): """Set-up coefficients and plugin for testing.""" super().setUp() self.plugin = Plugin() self.plugin.current_forecast = self.current_temperature_forecast_cube @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_with_statsmodels(self): """Test that the expected values for the location parameter are calculated when using the ensemble realizations with statsmodels. These expected values are compared to the results when using the ensemble mean and when statsmodels is not used to ensure that the results are similar.""" self.plugin.coefficients_cubelist = self.coeffs_from_statsmodels_realizations location_parameter = ( self.plugin._calculate_location_parameter_from_realizations() ) self.assertCalibratedVariablesAlmostEqual( location_parameter, self.expected_loc_param_statsmodels_realizations ) assert_array_almost_equal( location_parameter, self.expected_loc_param_mean, decimal=0 ) assert_array_almost_equal( location_parameter, self.expected_loc_param_no_statsmodels_realizations, decimal=0, ) @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_without_statsmodels(self): """Test that the expected values for the location parameter are calculated when using the ensemble realizations without statsmodels. These expected values are compared to the results when using the ensemble mean and when statsmodels is used to ensure that the results are similar.""" self.plugin.coefficients_cubelist = self.coeffs_from_no_statsmodels_realizations location_parameter = ( self.plugin._calculate_location_parameter_from_realizations() ) self.assertCalibratedVariablesAlmostEqual( location_parameter, self.expected_loc_param_no_statsmodels_realizations ) assert_array_almost_equal( location_parameter, self.expected_loc_param_mean, decimal=0 ) assert_array_almost_equal( location_parameter, self.expected_loc_param_statsmodels_realizations, decimal=0, )
class Test__spatial_domain_match(SetupCoefficientsCubes): """ Test the _spatial_domain_match method.""" def setUp(self): super().setUp() self.plugin = Plugin() def test_matching(self): """Test case in which spatial domains match.""" self.plugin.current_forecast = self.current_temperature_forecast_cube self.plugin.coefficients_cubelist = self.coeffs_from_mean self.plugin._spatial_domain_match() def test_unmatching_x_axis_points(self): """Test when the points of the x dimension do not match.""" self.current_temperature_forecast_cube.coord(axis="x").bounds = ( self.current_temperature_forecast_cube.coord(axis="x").bounds + 2.0 ) self.plugin.current_forecast = self.current_temperature_forecast_cube self.plugin.coefficients_cubelist = self.coeffs_from_mean msg = "The points or bounds of the x axis given by the current forecast" with self.assertRaisesRegex(ValueError, msg): self.plugin._spatial_domain_match() def test_unmatching_x_axis_bounds(self): """Test when the bounds of the x dimension do not match.""" self.current_temperature_forecast_cube.coord(axis="x").bounds = [ [-35, -5], [-5, 5], [5, 35], ] self.plugin.current_forecast = self.current_temperature_forecast_cube self.plugin.coefficients_cubelist = self.coeffs_from_mean msg = "The points or bounds of the x axis given by the current forecast" with self.assertRaisesRegex(ValueError, msg): self.plugin._spatial_domain_match() def test_unmatching_y_axis(self): """Test case in which the y-dimensions of the domains do not match.""" self.current_temperature_forecast_cube.coord(axis="y").bounds = ( self.current_temperature_forecast_cube.coord(axis="y").bounds + 2.0 ) self.plugin.current_forecast = self.current_temperature_forecast_cube self.plugin.coefficients_cubelist = self.coeffs_from_mean msg = "The points or bounds of the y axis given by the current forecast" with self.assertRaisesRegex(ValueError, msg): self.plugin._spatial_domain_match() def test_skipping_spot_forecast(self): """Test passing a spot forecast. In this case, the spatial domain is not checked.""" self.plugin.current_forecast = self.current_forecast_spot_cube self.plugin._spatial_domain_match()
def setUp(self): """Set-up coefficients and plugin for testing.""" super().setUp() self.plugin = Plugin() self.plugin.current_forecast = self.current_temperature_forecast_cube self.plugin.coefficients_cubelist = self.coeffs_from_mean
def test_end_to_end_point_by_point_sites_realizations(self): """An example end-to-end calculation when a separate set of coefficients are computed for each site using the realizations as the predictor. This repeats the test elements above but all grouped together.""" plugin = Plugin(predictor="realizations") calibrated_forecast_predictor, calibrated_forecast_var = plugin.process( self.current_forecast_spot_cube, self.coeffs_from_realizations_sites ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_predictor.data, self.expected_loc_param_realizations_sites, ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_var.data, self.expected_scale_param_realizations_sites ) self.assertEqual(calibrated_forecast_predictor.dtype, np.float32)
def setUp(self): """Set-up coefficients and plugin for testing.""" super().setUp() self.optimised_coeffs = dict( zip( self.coeffs_from_mean.coord("coefficient_name").points, self.coeffs_from_mean.data, )) self.plugin = Plugin() self.plugin.current_forecast = self.current_temperature_forecast_cube
class Test__spatial_domain_match(SetupCoefficientsCubes): """ Test the _spatial_domain_match method.""" def setUp(self): super().setUp() self.plugin = Plugin() def test_matching(self): """Test case in which spatial domains match.""" self.plugin.current_forecast = self.current_temperature_forecast_cube self.plugin.coefficients_cube = self.coeffs_from_mean self.plugin._spatial_domain_match() def test_unmatching_x_axis(self): """Test case in which the x-dimensions of the domains do not match.""" self.current_temperature_forecast_cube.coord(axis="x").points = ( self.current_temperature_forecast_cube.coord(axis="x").points * 2.0) self.plugin.current_forecast = self.current_temperature_forecast_cube self.plugin.coefficients_cube = self.coeffs_from_mean msg = "The domain along the x axis given by the current forecast" with self.assertRaisesRegex(ValueError, msg): self.plugin._spatial_domain_match() def test_unmatching_y_axis(self): """Test case in which the y-dimensions of the domains do not match.""" self.current_temperature_forecast_cube.coord(axis="y").points = ( self.current_temperature_forecast_cube.coord(axis="y").points * 2.0) self.plugin.current_forecast = self.current_temperature_forecast_cube self.plugin.coefficients_cube = self.coeffs_from_mean msg = "The domain along the y axis given by the current forecast" with self.assertRaisesRegex(ValueError, msg): self.plugin._spatial_domain_match()
class Test__calculate_location_parameter_from_mean( SetupCoefficientsCubes, EnsembleCalibrationAssertions ): """Test the __calculate_location_parameter_from_mean method.""" def setUp(self): """Set-up coefficients and plugin for testing.""" super().setUp() self.plugin = Plugin() self.plugin.current_forecast = self.current_temperature_forecast_cube self.plugin.coefficients_cubelist = self.coeffs_from_mean @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_basic(self): """Test that the expected values for the location parameter are calculated when using the ensemble mean. These expected values are compared to the results when using the ensemble realizations to ensure that the results are similar.""" location_parameter = self.plugin._calculate_location_parameter_from_mean() self.assertCalibratedVariablesAlmostEqual( location_parameter, self.expected_loc_param_mean ) assert_array_almost_equal( location_parameter, self.expected_loc_param_realizations, decimal=0, ) @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_missing_additional_predictor(self): """Test that an error is raised if an additional predictor is expected based on the contents of the coefficients cube.""" self.plugin.coefficients_cubelist = self.coeffs_from_mean_alt msg = "The number of forecast predictors must equal the number" with self.assertRaisesRegex(ValueError, msg): self.plugin._calculate_location_parameter_from_mean()
class Test__calculate_scale_parameter(SetupCoefficientsCubes, EnsembleCalibrationAssertions): """Test the _calculate_scale_parameter method.""" def setUp(self): """Set-up the plugin for testing.""" super().setUp() self.plugin = Plugin() self.plugin.current_forecast = self.current_temperature_forecast_cube @ManageWarnings( ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_basic(self): """Test the scale parameter is calculated correctly.""" self.plugin.coefficients_cubelist = self.coeffs_from_mean scale_parameter = self.plugin._calculate_scale_parameter() self.assertCalibratedVariablesAlmostEqual( scale_parameter, self.expected_scale_param_mean)
class Test__create_output_cubes(SetupCoefficientsCubes, EnsembleCalibrationAssertions): """Test the _create_output_cubes method.""" def setUp(self): """Set-up the plugin for testing.""" super().setUp() self.plugin = Plugin() self.plugin.current_forecast = self.current_temperature_forecast_cube @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_basic(self): """Test that the cubes created containing the location and scale parameter are formatted as expected.""" ( location_parameter_cube, scale_parameter_cube, ) = self.plugin._create_output_cubes( self.expected_loc_param_mean, self.expected_scale_param_mean ) self.assertEqual(location_parameter_cube, self.expected_loc_param_mean_cube) self.assertEqual(scale_parameter_cube, self.expected_scale_param_mean_cube)
class Test__calculate_location_parameter_from_mean( SetupCoefficientsCubes, EnsembleCalibrationAssertions): """Test the __calculate_location_parameter_from_mean method.""" def setUp(self): """Set-up coefficients and plugin for testing.""" super().setUp() self.optimised_coeffs = dict( zip( self.coeffs_from_mean.coord("coefficient_name").points, self.coeffs_from_mean.data, )) self.plugin = Plugin() self.plugin.current_forecast = self.current_temperature_forecast_cube @ManageWarnings( ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_basic(self): """Test that the expected values for the location parameter are calculated when using the ensemble mean. These expected values are compared to the results when using the ensemble realizations to ensure that the results are similar.""" location_parameter = self.plugin._calculate_location_parameter_from_mean( self.optimised_coeffs) self.assertCalibratedVariablesAlmostEqual(location_parameter, self.expected_loc_param_mean) assert_array_almost_equal( location_parameter, self.expected_loc_param_statsmodels_realizations, decimal=0, ) assert_array_almost_equal( location_parameter, self.expected_loc_param_no_statsmodels_realizations, decimal=0, )
def setUp(self): """Set-up the plugin for testing.""" super().setUp() self.plugin = Plugin()
class Test_process(SetupCoefficientsCubes, EnsembleCalibrationAssertions): """Test the process plugin.""" def setUp(self): """Set-up the plugin for testing.""" super().setUp() self.plugin = Plugin() @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_diagnostic_match(self): """Test that an error is raised if the diagnostic_standard_name does not match when comparing a forecast cube and coefficients cubelist.""" msg = "The forecast diagnostic" with self.assertRaisesRegex(ValueError, msg): self.plugin.process( self.current_wind_speed_forecast_cube, self.coeffs_from_mean ) @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_variable_setting(self): """Test that the cubes passed into the plugin are allocated to plugin variables appropriately.""" _, _ = self.plugin.process( self.current_temperature_forecast_cube, self.coeffs_from_mean ) self.assertEqual( self.current_temperature_forecast_cube, self.plugin.current_forecast ) self.assertEqual(self.coeffs_from_mean, self.plugin.coefficients_cubelist) @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_end_to_end(self): """An example end-to-end calculation. This repeats the test elements above but all grouped together.""" calibrated_forecast_predictor, calibrated_forecast_var = self.plugin.process( self.current_temperature_forecast_cube, self.coeffs_from_mean ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_predictor.data, self.expected_loc_param_mean ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_var.data, self.expected_scale_param_mean ) self.assertEqual(calibrated_forecast_predictor.dtype, np.float32) @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_end_to_end_point_by_point(self): """An example end-to-end calculation when a separate set of coefficients are computed for each grid point. This repeats the test elements above but all grouped together.""" calibrated_forecast_predictor, calibrated_forecast_var = self.plugin.process( self.current_temperature_forecast_cube, self.coeffs_from_mean_point_by_point ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_predictor.data, self.expected_loc_param_mean ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_var.data, self.expected_scale_param_mean ) self.assertEqual(calibrated_forecast_predictor.dtype, np.float32) @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_end_to_end_point_by_point_sites_realizations(self): """An example end-to-end calculation when a separate set of coefficients are computed for each site using the realizations as the predictor. This repeats the test elements above but all grouped together.""" plugin = Plugin(predictor="realizations") calibrated_forecast_predictor, calibrated_forecast_var = plugin.process( self.current_forecast_spot_cube, self.coeffs_from_realizations_sites ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_predictor.data, self.expected_loc_param_realizations_sites, ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_var.data, self.expected_scale_param_realizations_sites ) self.assertEqual(calibrated_forecast_predictor.dtype, np.float32) @ManageWarnings(ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_end_to_end_with_mask(self): """An example end-to-end calculation, but making sure that the areas that are masked within the landsea mask, are masked at the end.""" # Construct a mask and encapsulate as a cube. mask = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) mask_cube = self.current_temperature_forecast_cube[0].copy(data=mask) # Convention for IMPROVER is that land points are ones and sea points # are zeros in land-sea masks. In this case we want to mask sea points. expected_mask = np.array( [[False, True, True], [True, False, True], [True, True, False]] ) calibrated_forecast_predictor, calibrated_forecast_var = self.plugin.process( self.current_temperature_forecast_cube, self.coeffs_from_mean, landsea_mask=mask_cube, ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_predictor.data.data, self.expected_loc_param_mean ) self.assertArrayEqual(calibrated_forecast_predictor.data.mask, expected_mask) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_var.data.data, self.expected_scale_param_mean ) self.assertArrayEqual(calibrated_forecast_var.data.mask, expected_mask)
def setUp(self): """Set-up the plugin for testing.""" super().setUp() self.plugin = Plugin() self.plugin.current_forecast = self.current_temperature_forecast_cube
def setUp(self): super().setUp() self.plugin = Plugin()
class Test_process(SetupCoefficientsCubes, EnsembleCalibrationAssertions): """Test the process plugin.""" def setUp(self): """Set-up the plugin for testing.""" super().setUp() self.plugin = Plugin() @ManageWarnings( ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_variable_setting(self): """Test that the cubes passed into the plugin are allocated to plugin variables appropriately.""" _, _ = self.plugin.process(self.current_temperature_forecast_cube, self.coeffs_from_mean) self.assertEqual(self.current_temperature_forecast_cube, self.plugin.current_forecast) self.assertEqual(self.coeffs_from_mean, self.plugin.coefficients_cube) @ManageWarnings( ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_end_to_end(self): """An example end-to-end calculation. This repeats the test elements above but all grouped together.""" calibrated_forecast_predictor, calibrated_forecast_var = self.plugin.process( self.current_temperature_forecast_cube, self.coeffs_from_mean) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_predictor.data, self.expected_loc_param_mean) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_var.data, self.expected_scale_param_mean) self.assertEqual(calibrated_forecast_predictor.dtype, np.float32) @ManageWarnings( ignored_messages=["Collapsing a non-contiguous coordinate."]) def test_end_to_end_with_mask(self): """An example end-to-end calculation, but making sure that the areas that are masked within the landsea mask, are masked at the end.""" # Construct a mask and encapsulate as a cube. mask = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) mask_cube = self.current_temperature_forecast_cube[0].copy(data=mask) # Convention for IMPROVER is that land points are ones and sea points # are zeros in land-sea masks. In this case we want to mask sea points. expected_mask = np.array([[False, True, True], [True, False, True], [True, True, False]]) calibrated_forecast_predictor, calibrated_forecast_var = self.plugin.process( self.current_temperature_forecast_cube, self.coeffs_from_mean, landsea_mask=mask_cube, ) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_predictor.data.data, self.expected_loc_param_mean) self.assertArrayEqual(calibrated_forecast_predictor.data.mask, expected_mask) self.assertCalibratedVariablesAlmostEqual( calibrated_forecast_var.data.data, self.expected_scale_param_mean) self.assertArrayEqual(calibrated_forecast_var.data.mask, expected_mask)